2017-10-12 196 views
2

我有QTcpServer既可。我想從客戶端發送大量數據,以及如何在服務器上接收到所有數據時捕獲信號? 「while(socket-> bytesavailable)」不起作用。與QTcpSocket readyRead()信號發射兩次

例如:

時的QByteArray尺寸爲9000,這是從客戶端發送,這是4000或5000的服務器上...

例二:

在這case readyRead()SIGNAL被Emited 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

的數據不總是被髮送作爲單個分組。如果它足夠大,它可以作爲大塊數據發送。這可能是爲什麼你得到多個'readyRead'信號。 – vahancho

+0

如果您使用的是Qt 5.7或更新版本,您可以利用[讀取事務(http://doc.qt.io/qt-5/qdatastream.html#using-read-transactions)在'QDataStream'。看看在[財富客戶示例](http://doc.qt.io/qt-5/qtnetwork-fortuneclient-example.html),看看它是如何實現的。 – thuga

回答

3

TCP不發送消息,它是一個數據流。這意味着您不能只讀取那裏的所有數據,並考慮這一條消息。相反,人們通常會發送一個包含消息大小的頭文件,然後接收者知道要讀取多少消息才能獲得整個消息(並且只是這一個,而不是讀入下一個)。

這意味着你的插槽會做這樣的事情

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

你可以把一條線就像

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

在時隙的開始,那麼你就不會關心人,如果每條消息發出的信號不止一次。

注意,上面的代碼需要額外的錯誤處理,例如您必須確保第一個read讀取所有4個字節,並始終處理返回值-1。

+0

我認爲,這是非常helpfull.but我有和問題,現在是我「UINT32」 和使用不匹配的電話插座 - >讀(QByteArray中) – Taz742

+0

有對'::與QTcpSocket重載read',一個字節數組並返回讀取的字節數,另一個返回'QByteArray'。您必須根據您使用的代碼調整代碼。答案中的代碼會使用字節數組,'buffer'會是一個簡單的'char []' –

+0

謝謝,這個問題解決了) – Taz742