在消息前加上消息的大小

Prepending a message with the size of the message

本文关键字:消息      更新时间:2023-10-16

我正在写一些与服务器-客户端相关的东西,我在这里有这个代码片段:

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

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

我正在想办法做到这一点,但readwrite只接受字符,所以我可以在一个字符中发送的最大消息大小指标是127。我希望最大长度为65536,但我能想到的唯一方法是先设置一个size-of-size-of-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);

但是我想要一个更优雅的解决方案,如果有的话

在通过流发送消息时,在消息有效负载之前发送固定大小的头是一种非常常见的技术。这个头可以包括许多不同的信息片段,但它总是包括有效负载大小。在最简单的情况下,您可以发送编码为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);

读写工作与字节流。对于它们来说,字节是字符还是其他形式的数据都无关紧要。您可以通过将其地址转换为char*并发送4字节来发送一个4字节的整数。在接收端,将4字节转换回int型。(如果机器是不同类型的,您可能还会遇到端序问题,需要将字节重新排列成int型。