在前面添加消息大小的消息

时间:2014-07-25 17:19:27

标签: c++ qt sockets networking

我正在写一些与服务器相关的服务器,我在这里有这段代码:

char serverReceiveBuf[65536];
client->read(serverReceiveBuf, client->bytesAvailable());
handleConnection(serverReceiveBuf);

每当服务器发出readyRead()信号时读取数据。我在本地网络上测试时使用bytesAvailable()很好,因为没有延迟,但是当我部署程序时,我想确保在handleConnection()之前收到整个消息。

我正在考虑如何做到这一点,但readwrite只接受字符,因此我可以在一个字符中发送的最大邮件大小指示符为127.我希望最大大小为65536,但我能想到的唯一方法是首先使用size-of-size-message变量。

我将代码重写为:

char serverReceiveBuf[65536];
char messageSizeBuffer[512];
int messageSize = 0, i = 0; //max value of messageSize = 65536
client->read(messageSizeBuffer,512);
while((int)messageSizeBuffer[i] != 0 || i <= 512){
    messageSize += (int) messageSizeBuffer[i];
    //client will always send 512 bytes for size of message size
    //if message size < 512 bytes, rest of buffer will be 0
}
client->read(serverReceiveBuf, messageSize);
handleConnection(serverReceiveBuf);

但如果存在,我会想要一个更优雅的解决方案。

2 个答案:

答案 0 :(得分:1)

通过流发送消息以在消息有效负载之前发送固定大小的标头是一种非常常见的技术。此标头可以包含许多不同的信息,但它始终包含有效负载大小。在最简单的情况下,您可以发送编码为uint16_t的邮件大小,最大有效负载大小为65535(如果这还不够,则为uint32_t)。只需确保使用ntohshtons处理字节顺序。

uint16_t messageSize;
client->read((char*)&messageSize, sizeof(uint16_t));
messageSize = ntohs(messageSize);
client->read(serverReceiveBuf, messageSize);
handleConnection(serverReceiveBuf);

答案 1 :(得分:0)

使用字节流进行读写工作。如果字节是字符或任何其他形式的数据,则对它们无关紧要。您可以通过将其地址转换为char *并发送4个字节来发送4字节整数。在接收端,将4个字节强制转换为int。 (如果机器属于不同类型,您可能还会遇到字节序问题,需要将字节重新排列为int。请参阅htonl及其表兄弟。)