Russian Qt Forum

Qt => Работа с сетью => Тема начата: RedDog от Декабрь 09, 2010, 10:07



Название: TcpServer не принимает сообщения
Отправлено: RedDog от Декабрь 09, 2010, 10:07
не пойму, почему не доходят сообщения до сервера:
вот сам сервер:
Код:
class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QTcpServer *server;
    QTcpSocket *serverSocket;
    Ui::Dialog *ui;
private slots:
    void on_serverConnect();
    void on_dataRead();
};

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()), this, SLOT(on_serverConnect()));
    server->listen(QHostAddress::Any, 3355);
}

void Dialog::on_serverConnect()
{
    serverSocket = server->nextPendingConnection();
    connect(serverSocket, SIGNAL(readyRead()), this, SLOT(on_dataRead()));
    QTextCursor curs = ui->textEdit->textCursor();
    curs.movePosition(QTextCursor::End);
    curs.insertText("Connected!\r\n");
}

void Dialog::on_dataRead()
{
    QByteArray readingData;
    while(serverSocket->isReadable())
        readingData.append(serverSocket->readAll());
    QTextCursor curs = ui->textEdit->textCursor();
    curs.movePosition(QTextCursor::End);
    curs.insertText(readingData);
}
подключение происходит (т.е. слот on_serverConnect срабатывает, правда в дебаге с почему то раза 2-3 на брейкпоинте останавливается)

подключаюсь и отправляю ему сообщения вот так:

Код:
CServerConnection::CServerConnection(QObject *parent) :
    QObject(parent)
{
    connection = new QTcpSocket(this);
    connection->connectToHost("localhost", 3355, QIODevice::ReadWrite);
    connection->waitForConnected();
}

void CServerConnection::SendData(QByteArray data)
{
    if (!connection->isOpen())
        return;
    connection->write(QByteArray("Test String"));
    connection->flush();
}


Название: Re: TcpServer не принимает сообщения
Отправлено: BRE от Декабрь 09, 2010, 10:15
Что, по твоему делает этот код?
Код
C++ (Qt)
void Dialog::on_dataRead()
{
   while(serverSocket->isReadable())
       readingData.append(serverSocket->readAll());
}
 

Почему не почмотреть примеры и не разобраться как они работают, почему не почитать документацию?  :)


Название: Re: TcpServer не принимает сообщения
Отправлено: RedDog от Декабрь 09, 2010, 11:40
Благодарю за наводку, принимает.
Теперь другая проблема, в цикле шлю сообщения со структурой, принимает не пойми как, т.е. большая часть данных где то теряется, при чем именно пакеты целиком теряются, т.к выводит правильные значения, но всего 2-3 штуки и с большим и рандомным шагом.. Как тут можно реализовать?

вот что у сервера:
Код:
void Dialog::on_dataRead()
{
    struct
    {
        int CMD;
        int X;
        int Y;
        int Z;
        int Power;
    } sendingStruct;
   
    QByteArray readingData;
    while(serverSocket->bytesAvailable() > 0)
        readingData.append(serverSocket->readAll());
    memcpy(&sendingStruct, readingData.data() +1, sizeof(sendingStruct));
    QTextCursor curs = ui->textEdit->textCursor();
    curs.movePosition(QTextCursor::End);
    QString text = QString("CMD= %1\r\nX= %2\r\nY= %3\r\nZ= %4\r\nPower= %5").arg(sendingStruct.CMD).
                   arg(sendingStruct.X).arg(sendingStruct.Y).arg(sendingStruct.Z).arg(sendingStruct.Power);
    curs.insertText(text);
}
с QDataStream из примеров поставки не понял как длину пакета определять.

вот что идет с клиента:

Код:
void CServerConnection::SendData(QMap<QString, int> data)
{
    if (!connection->isOpen())
        return;

    struct
    {
        int CMD;
        int X;
        int Y;
        int Z;
        int Power;
    } sendingStruct;
    for (int i = 0; i < 100; i++)
    {
        sendingStruct.CMD = 33;
        sendingStruct.X = i;
        sendingStruct.Y = i+1;
        sendingStruct.Z = i*2;
        sendingStruct.Power = i*i;
        sendData.clear();
        char *buf = new char[sizeof(sendingStruct)];
        memcpy(buf, &sendingStruct,sizeof(sendingStruct));
        sendData.append(STX); // начало пакета
        sendData.append(buf, sizeof(sendingStruct));
        sendData.append(ETX); // конец пакета
        connection->write(sendData);
        connection->waitForBytesWritten();
        delete[] buf;
    }
}


Название: Re: TcpServer не принимает сообщения
Отправлено: Amigo_sa от Декабрь 09, 2010, 11:49
В корне неправильно использовать memcpy для того чтобы записать структуру в бинарный буфер. Потому что мы в общем случае не знаем, как именно структура в памяти располагается. Надо написать функцию для упаковки структуры в поток и восстановления. Как вариант переопределить метод >> у BinaryStream


Название: Re: TcpServer не принимает сообщения
Отправлено: RedDog от Декабрь 09, 2010, 11:54
В корне неправильно использовать memcpy для того чтобы записать структуру в бинарный буфер. Потому что мы в общем случае не знаем, как именно структура в памяти располагается. Надо написать функцию для упаковки структуры в поток и восстановления. Как вариант переопределить метод >> у BinaryStream
ну я всегда полагал, что она располагается линейно в памяти, в конце концов столько было примеров по поводу записи структуры в файл и ее восстановления оттуда, и ни у кого вроде с восстановлением проблем не возникало (если структура не содержит в себе указателей).
Но это все лирика, вопрос в другом: куда деваются пакеты и как их достать все из сети?


Название: Re: TcpServer не принимает сообщения
Отправлено: BRE от Декабрь 09, 2010, 12:05
Но это все лирика, вопрос в другом: куда деваются пакеты и как их достать все из сети?
Они не куда не деваются, ты их вычитываешь с помощью readAll к себе в буфер, только обрабатывашь только первую структуру из всего пакета.

Так ты ничего работающего не напишешь, поверь. Нужны минимальные базовые знания.  ;)


Название: Re: TcpServer не принимает сообщения
Отправлено: RedDog от Декабрь 09, 2010, 12:20
Нужны минимальные базовые знания.  ;)
 
просьба развернуть ответ! ;)
сделал через QTcpSocket::read

Код:
    char *buf = new char [sizeof(sendingStruct) + 2];
    while(serverSocket->bytesAvailable() > 0)
    {
        serverSocket->read(buf, sizeof(sendingStruct) + 2);
        memcpy(&sendingStruct, buf +1, sizeof(sendingStruct));
     ........
    }
остается вопрос, в случае если длина пакета меньше sizeof(sendingStruct) + 2 как тогда быть?


Название: Re: TcpServer не принимает сообщения
Отправлено: BRE от Декабрь 09, 2010, 12:25
А ты посмотри в примерах Qt как сделано там.  ;)


Название: Re: TcpServer не принимает сообщения
Отправлено: RedDog от Декабрь 09, 2010, 13:59
А ты посмотри в примерах Qt как сделано там.  ;)
Всё поговорками говорил.(с) к/ф Брат.
Ты имеешь ввиду пример Fortune Client/Server
и будет правильней через QDataStream делать?


Название: Re: TcpServer не принимает сообщения
Отправлено: BRE от Декабрь 09, 2010, 15:36
Ты имеешь ввиду пример Fortune Client/Server
Да.

и будет правильней через QDataStream делать?
Да.
Что бы понять почему, стоит вспомнить о порядке следования байт на разных архитектурах, о сетевом порядке байт. QDataStream о этом знает и будет все делать как надо.


Название: Re: TcpServer не принимает сообщения
Отправлено: RedDog от Декабрь 09, 2010, 16:04
Что бы понять почему, стоит вспомнить о порядке следования байт на разных архитектурах, о сетевом порядке байт. QDataStream о этом знает и будет все делать как надо.
в документации Qt такого нету, или не нашел.
а если сервера писать не на Qt, то как там определять последовательность байт?


Название: Re: TcpServer не принимает сообщения
Отправлено: BRE от Декабрь 09, 2010, 16:13
а если сервера писать не на Qt, то как там определять последовательность байт?
http://ru.wikipedia.org/wiki/Порядок_байтов

Там есть отдельная часть про сетевой порядок.