2013-06-29 14 views
0

我正在写一个简单的网络应用程序。客户端发送到服务器消息服务器在QTextEdit中打印并响应客户端。 我正在使用QTcpServer和QTcpSocket。 存在一个我无法解决的问题。接收数据是quint16 + QTime + QString作为QByteArrey发送。 我使用quint16来接收数据块的大小。出于某种原因,当客户机向服务器发送为什么QTcpSocket收到错误的数据?

next block size: 16 (quint16 value) 
block size: 18 

服务器获得:

next block size: 30073 (quint16 value) 
block size: 18 

正如你所看到的,由于某种原因,服务器从QDataStrem错误的变量值获得,它始终是30073.我不不明白为什么?

void Widget::slotSendToServer() 
{ 
    logTextEdit->append("slotSendToServer()"); 
    QByteArray arrBlock; 
    QDataStream serverSendStream(&arrBlock, QIODevice::ReadWrite); 
    QString messageStr = messageLineEdit->text(); 

    serverSendStream << quint16(0) << QTime::currentTime() 
        << messageStr; 

    serverSendStream.device()->seek(0); 
    serverSendStream << (quint16)(arrBlock.size() - sizeof(quint16)); 

    qDebug() << "next_block_size:" 
      <<(quint16)(arrBlock.size() - sizeof(quint16)) 
      << endl 
      << "full size of Byte arrey:" << arrBlock.size(); 

    tcpSocket->write(arrBlock); 
    messageLineEdit->clear(); 
} 



void Widget::slotReadClient() 
{ 
    logTextEdit->append("slotReadClient()"); 
    QTcpSocket *tcpSocket = (QTcpSocket*)sender(); 
    QDataStream clientReadStream(tcpSocket); 

    while(true) 
    { 
     if (!next_block_size) 
     { 
      if (tcpSocket->bytesAvailable() < sizeof(quint16)) 
      { 
       break; 
      } 
      clientReadStream >> next_block_size; 
     } 

     if (tcpSocket->bytesAvailable() < next_block_size) 
     { 
      break; 
     } 
     QTime time; 
     QString messageTextStr; 
     clientReadStream >> time >> messageTextStr; 

     QString messageCompleteStr = 
       time.toString() + " " + "Client has sent - " 
           + messageTextStr; 
     logTextEdit->append("Message received: "); 
     logTextEdit->append(messageCompleteStr); 

     next_block_size = 0; 

     sendToClient(tcpSocket, 
        "Server Response: Received \"" 
         + messageTextStr + "\""); 
    } 
} 
+0

TL; DR!请缩小范围并只发布相关代码。 –

+0

@Joachim Pileborg完成。 –

+0

你可以尝试的两件事:代替使用流和流操作符,可以尝试使用套接字函数来编写/读取(比如['write'](http://qt-project.org/doc/qt-5.0/) qtcore/qiodevice.html#write)和['read'](http://qt-project.org/doc/qt-5.0/qtcore/qiodevice.html#read))。第二件事是尝试检查发送方和接收方的字节顺序,它们是否一样? –

回答

2

你应该确保变量next_block_size每次套接字连接时初始化为0。

如果不重复使用相同的QTcpSocket对象,这可以在Widget类的构造函数来完成,或者如果你这样做,在连接插槽信号connected()

-1

我不知道你为什么这么做很复杂。 这应该工作:

void Widget::slotSendToServer() 
{ 
    logTextEdit->append("slotSendToServer()"); 
    QByteArray arrBlock; 
    QDataStream serverSendStream(tcpSocket); 

    serverSendStream << QTime::currentTime() 
        << messageLineEdit->text(); 
    messageLineEdit->clear(); 
} 

void Widget::slotReadClient() 
{ 
    logTextEdit->append("slotReadClient()"); 
    QTcpSocket *tcpSocket = (QTcpSocket*)sender(); 
    QDataStream clientReadStream(tcpSocket); 

    QTime time; 
    QString message; 

    clientReadStream >> time >> message; 

    emit YourSignal(time, message); 
} 

您不必担心大小,QDataStream跟踪它,你只需要保持的读取相同的顺序,因为它是在写完成的,所以你的缓冲区arrBlock是浪费的代码。


根据 documentation我的代码应该阻止读取时不是所有数据都可用,这只是缺点。对于像日期和一些字符串这样的小数据,它永远不会发生。

关于你的代码,你已经搞乱了你的阅读器while循环肯定,所以这里是没有这个循环的更正。

void Widget::slotReadClient() 
{ 
    logTextEdit->append("slotReadClient()"); 
    QTcpSocket *tcpSocket = (QTcpSocket*)sender(); 
    QDataStream clientReadStream(tcpSocket); 

    if (next_block_size==0) { 
     // need to read data size 
     if (tcpSocket->bytesAvailable() < sizeof(quint16)) 
      return; // wait for next signal 
     // next_block_size must be type of qint16 
     clientReadStream >> next_block_size; 
    } 
    if (tcpSocket->bytesAvailable() < next_block_size) { 
     // not enought data to complete read immediately 
     return; // wait for next signal 
    } 
    QTime time; 
    QString messageTextStr; 
    clientReadStream >> time >> messageTextStr; 
    QString messageCompleteStr = 
       time.toString() + " " + "Client has sent - " 
           + messageTextStr; 
    logTextEdit->append("Message received: "); 
    logTextEdit->append(messageCompleteStr); 

    // mark that data read has been finished 
    next_block_size = 0; 
} 
+0

所以,即使我有一个大的文件我钢不关心尺寸? –

+0

如果您使用QDataStream写入/读取数据比no。它嵌入了所有必需的信息。对于大量数据,阻塞线程可能存在问题,但您的示例没有此问题。 –

+1

这不起作用。当接收到一些数据时,插槽被调用,而不是在读取消息所需的所有数据时,所以如果没有足够的可用字节,'QDataStream :: status()'将返回'QDataStream :: ReadPastEnd'。这就是为什么您必须使用一种方法来确定整个邮件是否已到达,方法是预先添加邮件大小或在邮件中附加邮件结束标志。 – alexisdm

相关问题