2017-10-12 40 views
2

私はQTcpServerを持っています。クライアント側から大量のデータを送信し、サーバー上ですべてのデータが受信されたときに信号をキャッチする方法を教えてください。 while(socket-> bytesavailable)は動作しません。例えばQTcpSocket readyRead()シグナルが2回発行されました

qbytearrayサイズは、それが4000または5000のサーバー上で、クライアントから送信された、9000です...

例2:本で

case readyRead()SIGNALは8回エミットされます。

void Client::SendMessage(std::vector<QString>) 
{ 
    MyClass _Send; 
      _Send.Age = 22; 
      _Send.School = 14; 
      _Send.Name = "Taz"; 

    QVector<MyClass2> vv; 

    for (int i = 0; i < 15000; i++) { 
     vv.push_back(MyClass2(24, "leri")); 
     vv.push_back(MyClass2(22, "tazo")); 
    } 

    _Send.vctr = vv; 

    QByteArray bytes; 
    QDataStream stream(&bytes, QIODevice::WriteOnly); 

    int FunctionUID = 331; 
    int ij, ik = ij = 169; 
    MyClass2 faf(-31, "15"); 

    stream << FunctionUID << _Send << faf << ij << ik; 

    socket->write(bytes); 
} 



void Server::ImReady() 
{ 
    QByteArray buf; 

    buf = socket->readAll(); 

    QDataStream stream(&buf, QIODevice::ReadOnly); 

    int FunctionUID, ij, ik; 
    MyClass vv; 
    MyClass2 vv1; 

    stream >> FunctionUID >> vv >> vv1 >> ij >> ik; 

    qDebug() << vv.vctr.size() << "faf"; 
} 

void Server::incomingConnection(qintptr val) 
{ 
    qDebug() << "Client Connected" << val; 

    socket = new QTcpSocket; 
    socket->setSocketDescriptor(val); 

    if (!socket) { 
     return; 
    } 

    connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); 
    connect(socket, SIGNAL(readyRead()), this, SLOT(ImReady())); 
} 
+0

データが必ずしも1つのパケットとして送信されるわけではありません。十分な大きさであれば、データのまとまりとして送信できます。おそらく、なぜ、複数の 'readyRead'シグナルが得られるのでしょうか。 – vahancho

+0

Qt 5.7以降を使用している場合は、 'QDataStream'に[read transactions](http://doc.qt.io/qt-5/qdatastream.html#using-read-transactions)を利用することができます。 [fortuneクライアントの例](http://doc.qt.io/qt-5/qtnetwork-fortuneclient-example.html)を見て、実装方法を確認してください。 – thuga

答えて

3

TCPはメッセージを送信しません。これはデータストリームです。つまり、そこにあるすべてのデータを読み取るだけでは、この1つのメッセージを検討することはできません。代わりに、通常、メッセージサイズを含むヘッダーを送信します。次に、受信者は、メッセージ全体を取得するためにどれくらい読み込むべきかを知っています。

これはあなたのスロットはあなたがスロットの初めに

if (socket->bytesAvailable() == 0) 
    return; 

ような行を置くことができ、かつならば、あなたは全然気にしないだろう、この

void Server::ImReady() 
{ 
    uint32 size; 
    socket->read(&size, 4); 
    uint32 readTotal = 0; 
    do { 
    readTotal += socket->read(buffer, size-readTotal); 
    } while (readTotal < size); 
} 

ような何かをするだろう意味シグナルはメッセージごとに複数回送信されます。

上記のコードは追加のエラー処理が必要であることに注意してください。最初のreadがすべて4バイトを読み込み、常に-1の戻り値を処理することを確認する必要があります。

+0

私は、これは非常に有用です。しかし、私は合計問題を持っている、それは今私 'uint32' と一致する呼び出しsocket-> read(QByteArray) – Taz742

+0

とオーバーロードが 'QTcpSocket :: read'、読み込まれたバイト数を返し、もう1つは 'QByteArray'を返します。どちらを使用するかによって、コードを適合させる必要があります。答えのコードはバイト配列を使用し、 'buffer'は単純な' char [] ' –

+0

になります。この問題は解決していただきありがとうございます) – Taz742

関連する問題