我尝试使用Qt处理长度先前的TCP消息。我有以下方法:
QByteArray con::read()
{
QByteArray s;
s = _pSocket->read(4);
if (s.length() == 4) {
int size = char_to_int32(s);
s = _pSocket->read(size);
}
return s;
}
嗯,它不起作用。看起来我在读取前4个字节后丢失了所有数据:第一次读取工作正常,但read(size)
没有返回任何内容。有办法解决这个问题吗?
char_to_int32是:
int char_to_int32(QByteArray s)
{
int size = 0;
size |= (s.at(0) << 24);
size |= (s.at(1) << 16);
size |= (s.at(2) << 8);
size |= (s.at(3));
return size;
}
编辑:
发送功能(普通C):
int send(int connfd, const unsigned char* message, unsigned int size) {
int c;
unsigned char* bytes = (unsigned char*) malloc(4 + size);
int32_to_char(size, bytes); // converts message size to 4 bytes
memcpy(bytes + 4, message, size);
c = write(connfd, bytes, 4 + size);
free(bytes);
if (c <= 0)
return -1;
else
return 0;
}
顺便说一下,当我调用_pSocket-&gt; readAll()时,会读取整个数据包,包括4字节大小和消息本身。
编辑:
void int32_to_char(uint32_t in, char* bytes) {
bytes[0] = (in >> 24) & 0xFF;
bytes[1] = (in >> 16) & 0xFF;
bytes[2] = (in >> 8) & 0xFF;
bytes[3] = in & 0xFF;
return;
}
答案 0 :(得分:3)
当您使用QByteArray QIODevice::read(qint64 maxSize)
功能时,可能无法正确检测错误:
此功能无法报告错误;返回一个空的QByteArray()可能意味着当前没有数据可供读取,或者发生错误。
有些事情要尝试:
使用报告错误的qint64 QIODevice::read(char* data, qint64 maxSize)
:
如果发生错误...此函数返回-1。
致电QIODevice::errorString
和QAbstractSocket::error
,了解问题所在。
QAbstractSocket::error
错误信号。如果这是您正在创建的新协议,请尝试使用QDataStream
进行序列化,这会自动处理长度前缀并且与平台无关。如果混合使用不同endienness的平台,char_to_int32
将会中断,并且可能在不同操作系统或编译器之间中断,因为int
不能保证为32位(定义为at least 16 bits })。
QDataStream
,请至少使用htons, ntohs ...功能。修改强>
以下是一些显示hton / ntoh用法的示例代码。请注意,使用uint32_t
而不是int
,因为它保证为32位。我还在编码/解码中使用了memcpy
而不是指针强制转换来防止出现锯齿和对齐问题(为了简洁起见,我刚刚在测试函数中进行了强制转换)。
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
void encode(uint32_t in, char* out)
{
/* Host to Network long (32 bits) */
const uint32_t t = htonl(in);
memcpy(out, &t, sizeof(t));
}
uint32_t decode(char* in)
{
uint32_t t;
memcpy(&t, in, sizeof(t));
/* Network to Host long (32 bits) */
return ntohl(t);
}
void test(uint32_t v)
{
char buffer[4];
printf("Host Input: %08x\n", v);
encode(v, buffer);
printf("Network: %08x\n", *((uint32_t*)buffer));
printf("Host Output: %08x\n\n", decode(buffer));
}
int main(int argc, char** argv)
{
test(0);
test(1);
test(0x55);
test(0x55000000);
return 0;
}