美好的一天。
我正在发送一个用于通过 TCP 进行日志记录的自定义协议(protocol),如下所示:
Timestamp (uint32_t -> 4 bytes)
Length of message (uint8_t -> 1 byte)
Message (char -> Length of message)
时间戳被转换为 BigEndian
进行传输,一切都正确,除了一个小细节:填充
时间戳是单独发送的,但是我的应用程序(在 Ubuntu 下使用 BSD 套接字)不只是发送时间戳(4 个字节),而是自动将两个字节的填充附加到消息中。
Wireshark 正确地识别了这一点,并将两个无关的字节标记为填充,但是 QTcpSocket(Qt 5.8,mingw 5.3.0)显然假设这两个额外的字节实际上是有效负载,这显然弄乱了我的协议(protocol)。
有什么方法可以让我“教”QTcpSocket 忽略填充(就像它应该的那样)或者有什么方法可以摆脱填充吗?
如果可能的话,我想避免执行整个“创建足够大的缓冲区并在其中预组装整个数据包,以便一次性发送出去”的方法。
非常感谢。
因为有人问,所以发送数据的代码是:
return
C->sendInt(entry.TS) &&
C->send(&entry.LogLen, 1) &&
C->send(&entry.LogMsg, entry.LogLen);
其中 sendInt 声明为(Src
为参数):
Src = htonl(Src);
return send(&Src, 4);
其中“send”声明为(Source
和 Len
为参数):
char *Src = (char *)Source;
while(Len) {
int BCount = ::send(Sock, Src, Len, 0);
if(BCount < 1) return false;
Src += BCount;
Len -= BCount;
}
return true;
::send 是标准的 BSD 发送函数。
读取是通过QTcpSocket
完成的:
uint32_t timestamp;
if (Sock.read((char *)×tamp, sizeof(timestamp)) > 0)
{
uint8_t logLen;
char message[256];
if (Sock.read((char *)&logLen, sizeof(logLen)) > 0 &&
logLen > 0 &&
Sock.read(message, logLen) == logLen
) addToLog(qFromBigEndian(timestamp), message);
}
Sock
是QTcpSocket
实例,已经连接到主机,addToLog
是处理函数。
还需要注意的是,发送端需要在嵌入式系统上运行,因此不能使用QTcpServer
。
最佳答案
您的读取逻辑似乎不正确。你有...
uint32_t timestamp;
if (Sock.read((char *)×tamp, sizeof(timestamp)) > 0)
{
uint8_t logLen;
char message[256];
if (Sock.read((char *)&logLen, sizeof(logLen)) > 0 &&
logLen > 0 &&
Sock.read(message, logLen) == logLen
) addToLog(qFromBigEndian(timestamp), message);
}
来自 QTcpSocket::read(data, MaxSize)
的文档它...
Reads at most maxSize bytes from the device into data, and returns the number of bytes read
如果您对 Sock.read
的调用之一读取了部分数据怎么办?您本质上是丢弃该数据,而不是缓冲它以供下次重用。
假设您有一个适当范围的QByteArray
...
QByteArray data;
你的阅读逻辑应该更符合......
/*
* Append all available data to `data'.
*/
data.append(Sock.readAll());
/*
* Now repeatedly read/trim messages from data until
* we have no further complete messages.
*/
while (contains_complete_log_message(data)) {
auto message = read_message_from_data(data);
data = data.right(data.size() - message.size());
}
/*
* At this point `data' may be non-empty but doesn't
* contain enough data for a complete message.
*/
关于c++ - QTcpSocket 和 TCP 填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45074110/