recv只获取包的前4个字节 我在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; }

recv只获取包的前4个字节 我在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; },c,linux,sockets,udp,C,Linux,Sockets,Udp,我已经尝试使用MSG\u DONTWAIT标志将套接字设置为非阻塞,因为这解决了类似Python应用程序的问题,但是这只返回错误: Bytes received: -1; Message: 0 我对C++和套接字比较新,所以我可能没有看到一些东西。希望有人能帮我找出问题所在?如有必要,我可以提供其他信息。您收到的信息很好。你的调试代码并不像你想象的那样 printf的x说明符以十六进制打印无符号int参数。平台上的整数可能是32位。所以您只打印前4个字节 如果要以十六进制打印整个缓冲区,则需要

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

Bytes received: -1; Message: 0

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

您收到的信息很好。你的调试代码并不像你想象的那样

printf
x
说明符以十六进制打印无符号int参数。平台上的整数可能是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");
nbyt=recv(sockfd,buf,BUFFERSIZE,0);
fprintf(文件“%s%d;”%s\n,“接收字节:”,nbyt,“消息:”);
对于(offset=0;offset
*buf
在您的代码中表示接收到的数据数组中的第一个整数,因此您只打印接收到的UDP有效负载的前四个字节。

尽管存在前面提到的格式错误,但如果您收到“\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;
}

数据在缓冲区中。%x使printf在buf指向的位置查找无符号十六进制整数。因此,您的程序正在执行您告诉它的操作。你可能还想要别的东西。请注意,在recv()调用中,您已经设置了BUFFERSIZE字节的限制,而您分配的缓冲区至少要大四倍,具体取决于平台的int大小。请分配一个字符缓冲区,像现在一样调用recv()以获取数据,并将缓冲区指针传递给二进制数据的处理程序例程。printf()不是查看二进制内容的好选择。@arayq2 OP使用
int*buf=(int*)malloc(BUFFERSIZE)分配缓冲区上次我检查时,
malloc
需要很多字节。你是不是在考虑calloc
?还是C++数组-<代码>新< /代码>?@德伯特,你说得对!或者,由于指针衰减,您可以在传递之前在data init中执行第一个选项,并将元素数发送到函数中-很好而且是动态的。这就是问题所在!谢谢你帮助我!我一直在错误的地方寻找问题。现在我知道我一切都好了,只需要我把细节讲清楚就行了。再次感谢,也感谢所有回答的人@user1896512请点击旁边的复选框,随时接受答案。。。或者不,这取决于你。
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;
}