【问题标题】:Why is TCP server receiving corrupted messages?为什么 TCP 服务器接收到损坏的消息?
【发布时间】:2019-10-01 13:37:42
【问题描述】:

我正在尝试在同一端口上设置 TCP/UDP 服务器托管。

UDP 部分工作正常,但 TCP 部分无法正确接收消息。

我尝试使用 netcat 对其进行测试,例如。当我发送“TCP y u do dis”时,它会输出类似“D(”的内容并继续在 do while 循环中旋转。

    //Creating TCP listen socket
    tcp_listenfd=socket(AF_INET, SOCK_STREAM, 0);
    bzero(&tcp_servaddr, sizeof(tcp_servaddr));
    tcp_servaddr.sin_family=AF_INET;
    tcp_servaddr.sin_port=htons(atoi(tcp_port));
    tcp_servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    //Binding TCP socket
    setsockopt(tcp_listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    bind(tcp_listenfd,(struct sockaddr*)&tcp_servaddr,sizeof(tcp_servaddr));
    listen(tcp_listenfd, 10);

    //Creating UDP listen socket
    udp_listenfd=socket(AF_INET, SOCK_DGRAM, 0);
    bzero(&udp_servaddr, sizeof(udp_servaddr));
    udp_servaddr.sin_family=AF_INET;
    udp_servaddr.sin_port=htons(atoi(udp_port));
    udp_servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    //Binding UDP listen socket
    bind(udp_listenfd, (struct sockaddr*)&udp_servaddr, sizeof(udp_servaddr));

    //Clear descriptor set
    FD_ZERO(&rset);

    //Max file descriptor
    maxfd = max(tcp_listenfd, udp_listenfd)+1;

    while(1){
        // set listenfd and udpfd in readset
        FD_SET(tcp_listenfd, &rset);
        FD_SET(udp_listenfd, &rset);

        nready = select(maxfd, &rset, NULL, NULL, NULL);

        if (FD_ISSET(tcp_listenfd, &rset)) {
            printf("TCP ready!\n");
            len=sizeof(cli_addr);
            connfd = accept(tcp_listenfd, (struct sockaddr*)&cli_addr, &len);
            do {
                numbytes=recv(tcp_listenfd, tcp_buff, sizeof(tcp_buff), 0);
                printf("Received message: %s\n", tcp_buff);
            }while(strcmp(tcp_buff, "HELLO\n")!=0);
            send(tcp_listenfd, payload, strlen(payload)+1, 0);
            close(connfd);
            bzero(&cli_addr, sizeof(cli_addr));
        }

        if(FD_ISSET(udp_listenfd, &rset)){
            printf("UDP ready!\n");
            len=sizeof(cli_addr);
            do{
                recvfrom(udp_listenfd, udp_buff, 1024, 0,(struct sockaddr *)&cli_addr, &len);
            }while(strcmp(udp_buff, "HELLO\n")!=0);
            sendto(udp_listenfd, payload, strlen(payload)+1, 0, (struct sockaddr *)&cli_addr, len);
            close(udp_listenfd);
            bzero(&cli_addr, sizeof(cli_addr));
        }
    }

【问题讨论】:

  • 你打印出recv()返回的值了吗?由于 TCP 是一个流协议,即使成功,它也可以是 1 到 sizeof(tcp_buff) 之间的任何值,特别是任何给定的 recv() 调用写入缓冲区的字节数不能保证与传递给发送程序中任何较早的send() 调用的字节数。另请注意,printf("%s", [...]) 假定您传递给它的字符串将被 NUL/0 终止,这在recv() 返回后可能不是这种情况,因为recv() 在二进制级别上工作并且不遵循 C 字符串语义.
  • recv() 的返回值为 -1。字符串是空终止的,我已经用其他程序 client.c 测试了它,它通过 TCP 发送空终止的字符串。
  • @user3104311 这还不够好。仔细阅读 Jeremy 的评论。

标签: c sockets tcp network-programming


【解决方案1】:

好的,问题来了:

 connfd = accept(tcp_listenfd, (struct sockaddr*)&cli_addr, &len);
 do {
    numbytes=recv(tcp_listenfd, tcp_buff, sizeof(tcp_buff), 0);

在您的recv() 调用中,您传递的是tcp_listenfd,而您应该传递的是connfd。 (此外,您应该检查所有函数调用的返回值以确保函数成功,并在函数调用失败时采取适当的措施(例如通过perror() 打印错误消息)。请参阅每个函数的手册页有关返回值构成该函数的成功与失败的详细信息)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 2017-09-01
    • 1970-01-01
    相关资源
    最近更新 更多