Russian Qt Forum
Ноябрь 23, 2024, 07:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: QVector в QDataStream для передачи по сети! Помогите  (Прочитано 20185 раз)
lolbla2
Гость
« : Февраль 06, 2012, 12:35 »

Нужно передать вектор моей структуры Input, то есть QVector <Input *> data ; даже не знаю лучше ссылку или без ссылки, т.е. QVector <Input *> data или QVector <Input > data. Ну не важно и так и так не работает((( вообщем структура имеет следующий вид:
struct Input
{
    bool startflag;
    int player;
    bool t_dead;
    int t_dir;
    int t_posx;
    int t_posy;
    int t_movex;
    int t_movey;
    int b_posx;
    int b_posy;
    int b_dir;
};

QDataStream &operator<<(QDataStream &out, const Input &inp)
{
    out<<(quint32)inp.b_dir<<(quint32)inp.b_posx<<(quint32)inp.b_posy<<
         (quint32)inp.player<<(quint32)inp.t_dir<<(quint32)inp.t_movex<<
         (quint32)inp.t_movey<<(quint32)inp.t_posx<<(quint32)inp.t_posy<<
         inp.startflag<<inp.t_dead;
    return out;
}
QDataStream &operator>>(QDataStream &in, Input &inp)
{
    quint32 player;
    quint32 t_dir;
    quint32 t_posx;
    quint32 t_posy;
    quint32 t_movex;
    quint32 t_movey;
    quint32 b_posx;
    quint32 b_posy;
    quint32 b_dir;
    bool t_dead;
    bool startflag;
    in>>b_dir>>b_posx>>b_posy>>player>>t_dir>>t_movex>>t_movey>>t_posx>>t_posy>>startflag>>t_dead;
    inp.b_dir=b_dir;
    inp.b_posx=b_posx;
    inp.b_posy=b_posy;
    inp.player=player;
    inp.t_dir=t_dir;
    inp.t_movex=t_movex;
    inp.t_movey=t_movey;
    inp.t_posx=t_posx;
    inp.t_posy=t_posy;
    inp.startflag=startflag;
    inp.t_dead=t_dead;
    return in;
}

пытаюсь принимать :

void Widget::OnReceiveData()
{
    QMessageBox::information(this,"data received!","data received from client!");
    for(int i=0; i<sockets.size(); i++)
    {
        QDataStream in(sockets);
    in.setVersion(QDataStream::Qt_4_7);

    if (blockSize == 0) {
        if (sockets->bytesAvailable() < (int)sizeof(quint32))
            continue;
        in >> blockSize;
    }

    if (sockets->bytesAvailable() < blockSize)
        continue;
    in>> data; // здесь ошибка

    }
}



что он тут ругается типо не может найти операторы << и >> если они есть не пойму((

а если пытаюсь отправить:
void Widget::SendData()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_7);
//! [4] //! [6]
    out << (quint32)0;
    out << data;
    out.device()->seek(0);
    out << (quint32)(block.size() - sizeof(quint32));
    for(int i=0; i<sockets.size(); i++)
    {
        sockets->write(block);
    }

}

то другие ошибки возникают:
« Последнее редактирование: Февраль 06, 2012, 12:40 от lolbla2 » Записан
Orfus
Гость
« Ответ #1 : Февраль 06, 2012, 12:52 »

1)пользуйтесь тегам кода
2)В слоте void Widget::OnReceiveData() вместо поисков нужного сокета можно использовать
Код:
    QTcpSocket* TCPSocket = (QTcpSocket*)sender();
    QDataStream in(TCPSocket);
Рекомендовал бы даже если подключений много, для каждого подключения хранить blockSize отдельно.
Если машины не в локальной сети, неплохо бы повторить OnReceiveData() в конце метода OnReceiveData(), ибо новые пакеты придут, а сигнала не будет.

3)Про стрим не подскажу, но объясните мне кто нибудь зачем делать отдельный метод? Что мешает делать
Код:
in>>data.b_dir;
in>>data.b_posx;
in>>data.b_posy;
in>>data.player;
in>>data.t_dir;
in>>data.t_movex;
in>>data.t_movey;
in>>data.t_posx;
in>>data.t_posy;
in>>data.startflag;
in>>data.t_dead;

4) Делать сеть внутри GUI потока черевато.
5) после прочтения данных, стоило бы сделать blockSize=0;
« Последнее редактирование: Февраль 06, 2012, 13:06 от Orfus » Записан
lolbla2
Гость
« Ответ #2 : Февраль 06, 2012, 13:14 »

1)пользуйтесь тегам кода
2)В слоте void Widget::OnReceiveData() вместо поисков нужного сокета можно использовать
Код:
    QTcpSocket* TCPSocket = (QTcpSocket*)sender();
    QDataStream in(TCPSocket);
Рекомендовал бы даже если подключений много, для каждого подключения хранить blockSize отдельно.
Если машины не в локальной сети, неплохо бы повторить OnReceiveData() в конце метода OnReceiveData(), ибо новые пакеты придут, а сигнала не будет.

3)Про стрим не подскажу, но объясните мне кто нибудь зачем делать отдельный метод? Что мешает делать
Код:
in>>data.b_dir;
in>>data.b_posx;
in>>data.b_posy;
in>>data.player;
in>>data.t_dir;
in>>data.t_movex;
in>>data.t_movey;
in>>data.t_posx;
in>>data.t_posy;
in>>data.startflag;
in>>data.t_dead;

4) Делать сеть внутри GUI потока черевато.
5) после прочтения данных, стоило бы сделать blockSize=0;

Код:
QVector < Input *> data;
- такой тип имеет, поэтому думаю не получится как Вы имели в виду, мы ведь не знаем размер вектора который придёт по сети
Почему чревата сеть внутри GUI?


Насчёт тегов сори, я недавно на вашем форуме
« Последнее редактирование: Февраль 06, 2012, 13:24 от lolbla2 » Записан
Orfus
Гость
« Ответ #3 : Февраль 06, 2012, 13:19 »

GUI будет провисать в моменты объемных приёмов\передач. Я не имею ни малейшего понятия насколько велик поток трафика в ваших приложениях, но если он объёмный стоит задуматься  о классе для сети и отдельном потоке.
Записан
Странник
Гость
« Ответ #4 : Февраль 06, 2012, 13:26 »

по-моему операторы >> и << у вас объявлены для Input, а передавать вы пытаетесь Input*.
Записан
lolbla2
Гость
« Ответ #5 : Февраль 06, 2012, 13:34 »

GUI будет провисать в моменты объемных приёмов\передач. Я не имею ни малейшего понятия насколько велик поток трафика в ваших приложениях, но если он объёмный стоит задуматься  о классе для сети и отдельном потоке.


Ну вообще делаю игру танчики на подобии дендевской. Максимум 6 игроков. Как Вы уже наверно догадались структура для передачи данных имеет вид:
Код:
struct Input
{
    bool startflag;
    int player;
    bool t_dead;
    int t_dir;
    int t_posx;
    int t_posy;
    int t_movex;
    int t_movey;
    int b_posx;
    int b_posy;
    int b_dir;
};
Т.е. QVector из таких структур размерности количества игроков.

Серверное приложение отдельно.

Клиент когда сдвинул танчик или стрельнул, то серверу приходят от него данные и сервер в свою очередь всем игрокам рассылает данные о всех танчиках, но каждому не шлёт егошние данные, то есть игроку 1 шлёт данные о игроках 2,3,4,5,6. Игроку 2 данные о игроках 1,3,4,5,6 и т д.
Записан
lolbla2
Гость
« Ответ #6 : Февраль 06, 2012, 13:40 »

по-моему операторы >> и << у вас объявлены для Input, а передавать вы пытаетесь Input*.
пробовал менять на * и без не помогало
Записан
Orfus
Гость
« Ответ #7 : Февраль 06, 2012, 13:42 »

Всё же я убеждён что в QDataStream &operator>>(QDataStream &in, Input &inp) 38 байт жрутся напрасно.

p.s. представил уже как написать wallhack и speedhack  Крутой
Записан
lolbla2
Гость
« Ответ #8 : Февраль 06, 2012, 13:50 »

Всё же я убеждён что в QDataStream &operator>>(QDataStream &in, Input &inp) 38 байт жрутся напрасно.




Возможно но это пока ерунда по сравнению с глобальной проблемой - почему не пашут  эти перегруженные операторы))
Записан
Orfus
Гость
« Ответ #9 : Февраль 06, 2012, 14:28 »

.h
Код:
struct promp{
public:
    int  val1;
    int  val2;
    bool val3;
};
.cpp
Код:
QDataStream &operator>>(QDataStream &in, promp &inp){

    in>>inp.val1;
    in>>inp.val2;
    in>>inp.val3;

    return in;
}

QDataStream &operator>>(QDataStream &in, promp *inp){

    in>>inp->val1;
    in>>inp->val2;
    in>>inp->val3;

    return in;
}

QDataStream &operator<<(QDataStream &out, const promp &inp)
{
    out<<inp.val1<<inp.val2;
    out<<inp.val3;
    return out;
}

QDataStream &operator<<(QDataStream &out, const promp *inp)
{
    out<<inp->val1<<inp->val2;
    out<<inp->val3;
    return out;
}


int main(int argc,char** argv){
    QApplication app(argc,argv);


    promp p1;
    promp *p2= new promp();
    p1.val1=1;p2->val1=2;
    p1.val2=10;p2->val2=20;
    p1.val2=true;p2->val3=false;


    QFile f("temp.t");
    {
        f.open(QIODevice::WriteOnly);
        f.resize(0);
        QDataStream s(&f);
        s<<p1;
        f.close();
    }
    {
        f.open(QIODevice::ReadOnly);
        QDataStream s(&f);
        s>>p2;
        f.close();
        qWarning()<<"p1 write, p2 read\t"<< p2->val1 << p2->val2 << p2->val3;
    }
    {
        p2->val1=2;p2->val2=20;p2->val3=false;
        f.open(QIODevice::WriteOnly);
        f.resize(0);
        QDataStream s(&f);
        s<<p2;
        f.close();
    }

    {
        f.open(QIODevice::ReadOnly);
        QDataStream s(&f);
        s>>p1;
        f.close();
        qWarning()<<"p2 write, p1 read\t"<< p1.val1 << p1.val2 << p1.val3;
    }

    return 1;
}
Сравнивай, подстраивай под себя. У меня работают

Код:
Запускается D:\qt\projects\LIC_NEW\release\CRYPTER.exe...
p1 write, p2 read 1 1 true
p2 write, p1 read 2 20 false
D:\qt\projects\LIC_NEW\release\CRYPTER.exe завершился с кодом 1
Записан
Orfus
Гость
« Ответ #10 : Февраль 06, 2012, 14:31 »

Но всё равно, в отсутствии чего то глобального в структурке считаю что ты просто захламляешь стек вызовов.
Записан
lolbla2
Гость
« Ответ #11 : Февраль 06, 2012, 14:59 »

Но всё равно, в отсутствии чего то глобального в структурке считаю что ты просто захламляешь стек вызовов.

а попробуй засунь свою структуру в QVector и отправь её в QDataStream, а потом вытащи оттуда будет ли работать?
Записан
Orfus
Гость
« Ответ #12 : Февраль 06, 2012, 15:20 »

challenge accepted  Показает язык
Код:
int main(int argc,char** argv){
    QApplication app(argc,argv);

    promp p1,p2,p3,p4,p5;
    p1.val1=1;
    p1.val2=10;
    p1.val3=true;

    p2.val1=2;
    p2.val2=20;
    p2.val3=true;

    p3.val1=3;
    p3.val2=30;
    p3.val3=true;

    p4.val1=4;
    p4.val2=40;
    p4.val3=true;

    p5.val1=5;
    p5.val2=50;
    p5.val3=true;

    QVector<promp> players;

    players.append(p1);
    players.append(p2);
    players.append(p3);
    players.append(p4);
    players.append(p5);


    QFile f("temp.t");
    {
        f.open(QIODevice::WriteOnly);
        f.resize(0);
        QDataStream s(&f);
        s<<players;
        f.close();
    }


    p1.val1=0; p1.val2=0; p1.val3=false;
    p2.val1=0; p2.val2=0; p2.val3=false;
    p3.val1=0; p3.val2=0; p3.val3=false;
    p4.val1=0; p4.val2=0; p4.val3=false;
    p5.val1=0; p5.val2=0; p5.val3=false;
    players.clear();

    {
        f.open(QIODevice::ReadOnly);
        QDataStream s(&f);
        s>>players;
        f.close();
        for(int i=0; i<players.size();i++)
        qWarning()<<"p"<<i<<"\t"<< players.at(i).val1 << players.at(i).val2 << players.at(i).val3;
    }

    return 1;
}
Код:
Запускается D:\qt\projects\LIC_NEW\release\CRYPTER.exe...
p 0 1 10 true
p 1 2 20 true
p 2 3 30 true
p 3 4 40 true
p 4 5 50 true
D:\qt\projects\LIC_NEW\release\CRYPTER.exe завершился с кодом 1

Методы записи чтения те же. Структурка та же.
Записан
KrupaKarlo
Гость
« Ответ #13 : Февраль 06, 2012, 16:14 »

GUI будет провисать в моменты объемных приёмов\передач. Я не имею ни малейшего понятия насколько велик поток трафика в ваших приложениях, но если он объёмный стоит задуматься  о классе для сети и отдельном потоке.


Ну вообще делаю игру танчики на подобии дендевской. Максимум 6 игроков. Как Вы уже наверно догадались структура для передачи данных имеет вид:
Код:
struct Input
{
    bool startflag;
    int player;
    bool t_dead;
    int t_dir;
    int t_posx;
    int t_posy;
    int t_movex;
    int t_movey;
    int b_posx;
    int b_posy;
    int b_dir;
};
Т.е. QVector из таких структур размерности количества игроков.

Серверное приложение отдельно.

Клиент когда сдвинул танчик или стрельнул, то серверу приходят от него данные и сервер в свою очередь всем игрокам рассылает данные о всех танчиках, но каждому не шлёт егошние данные, то есть игроку 1 шлёт данные о игроках 2,3,4,5,6. Игроку 2 данные о игроках 1,3,4,5,6 и т д.

В Qt есть такая вещь как  Q_DECLARE_METATYPE
Код:
struct MyStruct
 {
     int i;
     ...
 };
 Q_DECLARE_METATYPE(MyStruct)

Это позволяет запихивать и доставать свои типы из QVariant ИМХО так будет попроще делать) чем структуры в сокет пихать
Записан
Orfus
Гость
« Ответ #14 : Февраль 06, 2012, 16:43 »

...
Это позволяет запихивать и доставать свои типы из QVariant ИМХО так будет попроще делать) чем структуры в сокет пихать


А разве Q_DECLARE_METATYPE(MyStruct) позволит запихнуть в QDataStream?

P.S.
.... мы ведь не знаем размер вектора который придёт по сети ....

blockSize по вашему что?
« Последнее редактирование: Февраль 06, 2012, 16:54 от Orfus » Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.11 секунд. Запросов: 20.