1

我正在尝试使用 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->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;
}
4

1 回答 1

3

当您使用该QByteArray QIODevice::read(qint64 maxSize)功能时,您可能无法正确检测错误:

该功能无法报错;返回一个空的 QByteArray() 可能意味着当前没有数据可供读取,或者发生了错误。

一些事情要尝试:

编辑

这是一些显示 hton/ntoh 用法的示例代码。请注意,使用uint32_tand notint因为它保证为 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;
}
于 2012-04-30T22:25:37.217 回答