3

我正在用 C++ 编写一个客户端应用程序以通过 UDP 广播接收二进制数据,但是无论缓冲区大小如何,我都无法接收前 4 个字节以外的任何内容。我检查了 Wireshark 中的数据包,我可以看到我的机器正在接收大约 1200 字节的数据。当我将此与我的客户端接收的内容进行比较时,我可以看到我正在获取数据包,但是剩余的数据丢失了。这是我的代码:

#define BUFFERSIZE 4096
int main()
{
    struct addrinfo hints, *servinfo, *p;
    int sockfd, i, nbyt;

    int *buf = (int*) malloc(BUFFERSIZE);

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE;

    getaddrinfo(NULL, "9011", &hints, &servinfo);

    sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
    bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen);

    FILE *file;
    file = fopen("file.txt", "w+");

    for (i=0;i<=45;i++)
    {
        nbyt = recv(sockfd, buf, BUFFERSIZE, 0);            
        fprintf(file, "%s %d; %s %x\n", "Bytes received:", nbyt, "Message:", *buf);
    }

    fclose(file);
    close(sockfd);
    free(buf);

    printf("%s\n", "Execution ended.");

    return 0;
}

我收到的一些数据的示例:

Bytes received: 1131; Message: 5b0
Bytes received: 1131; Message: 5b3
Bytes received: 1131; Message: 5b6
Bytes received: 1092; Message: 4e0

我尝试使用标志将套接字设置为非阻塞MSG_DONTWAIT,因为这解决了类似 Python 应用程序的问题,但是这只返回错误:

Bytes received: -1; Message: 0

我对 C++ 和套接字比较陌生,所以可能有一些我没有看到的东西。希望有人可以帮助我找出问题所在?如有必要,我可以提供更多信息。

4

3 回答 3

4

你收到它就好了。您的调试代码并没有按照您的想法执行。

以十六进制打印 unsigned int 参数的x说明符。printf您平台上的整数可能是 32 位的。所以你只打印前 4 个字节。

如果要以十六进制打印整个缓冲区,则需要自己编写循环来执行此操作(当然,也可以使用库)。

例如,我警告你我的 C 有点生疏(这不是目前执行此操作的最佳方法)......此外,这假设你的缓冲区始终是 sizeof(int) 的倍数,或者它'会丢失一些数据:

nbyt = recv(sockfd, buf, BUFFERSIZE, 0);            
fprintf(file, "%s %d; %s\n", "Bytes received:", nbyt, "Message:");
for (offset = 0; offset < nbyt/sizeof(int); ++offset) {
    fprintf(file, "%x ", buf[offset]);
}
fprintf(file, "\n");
于 2013-01-03T21:05:48.660 回答
1

*buf在您的代码中表示接收数据数组中的第一个整数,因此您只打印接收到的 UDP 有效负载的前四个字节。

于 2013-01-03T21:13:27.160 回答
1

尽管已经提到了格式错误,但如果您收到一个 '\0' 字符,则带有 %s 的格式化打印将在那里剪切字符串,而不管收到的实际字符数是多少。

为了调试明文,我使用了以下代码:

char escaped_char(char c)
{
    char escapable[12] =    {'\a','\b','\f','\n','\r','\t','\v','\\','\'','\"','\?','\0'};
    char escaped[12]   =    { 'a', 'b', 'f', 'n', 'r', 't', 'v','\\','\'','\"', '?', '0'};

    const char* escapable_end = escapable + 12;
    const char* ec;

    for(ec = escapable;ec != escapable_end;++ec)
    {
        if(c == *ec) return escaped[ec-escapable];
    }
    return 0;
}

/**
 * @param   buf     input buffer to escape
 * @param   len     length of contents in buf
 * @param   outlen  pointer to an integer, which receives the length of the returned string
 * @return          A newly allocated, C style escaped string, NULL on error
 * @warning         A returned string must be freed with free()
 */
char* aescape(const char* buf,size_t len,size_t* outlen)
{
    const char* buf_end = buf + len;
    const char* c;
    char ec;
    char* result;

    assert(buf && outlen);

    (*outlen) = len;

    for(c = buf;c != buf_end;++c)
    {
        if(escaped_char(*c))
        {
            ++*outlen;
        }
    }
    result = malloc((*outlen)+1);
    assert(result != NULL);
    if(result)
    {
        if((*outlen) > len)
        {
            char* out = result;
            for(c = buf;c != buf_end;++c)
            {
                ec = escaped_char(*c);
                if(ec)
                {
                    *out++ = '\\';
                    *out++ = ec;
                }
                else
                {
                    *out++ = *c;
                }
            }
        }
        else
        {
            memcpy(result,buf,len);
        }
        result[(*outlen)] = '\0';
    }
    else
    {
        (*outlen) = 0;
    }
    return result;
}
于 2013-01-03T21:55:27.403 回答