recv() 没有从网络中获取价值

recv() does not get value from network

我有一个典型的客户端服务器C套接字程序。

SERVER:
            if(ndp.cmd == 11)
            {   
                //ack1 = 0;
                puts("Query Command for Light 2");
                pthread_mutex_lock(&lock);  
                // ..Some critical stuff
                pthread_mutex_unlock(&lock);    
                printf("ID: %d, Level: %d\n", new.address, new.level);
                ack1 = new.level; //This result is showing correct on server
                ack1 = htonl(ack1);
                send(client_sock, &ack1, sizeof(ack1), 0);              
            }

CLIENT:
    printf("Query Actual level Light2\n");
    dp.id = 2;dp.cmd = 11; dp.active = 0; dp.level = 0; dp.group = 0; 
    if( send(sock , &dp , sizeof(dp) , 0) < 0) { puts("Send failed"); }
    sleep(1);
    ret = recv(sock , &level1 , sizeof(level1) , 0);
    printf("Number of bytes received: %d\n", ret); //Always gives 4
    fflush(stdout);
    printf("Light level %x\n", ntohl(level1) ); //This prints 0 (incorrect)
    fflush(stdout);
    sleep(5);


    printf("Query Actual level Light2\n");
    dp.id = 2;dp.cmd = 11; dp.active = 0; dp.level = 0; dp.group = 0; 
    if( send(sock , &dp , sizeof(dp) , 0) < 0) { puts("Send failed"); }
    sleep(1);
    ret = recv(sock , &level2 , sizeof(level2) , 0);
    printf("Number of bytes received: %d\n", ret); // Always gives 4
    fflush(stdout);
    printf("Light level %x\n", ntohl(level2) ); //This prints correct value
    fflush(stdout);
    close(sock);

Expected output:
Light level 32 (hex value for 50);
Light level 32

Actual output:
Light level 0
Light level 32

所以问题出在相同的请求上,客户端没有收到来自服务器的第一次发送,但下一个 recv() 给出了正确的值。

为什么第一个 recv() 的数据丢失了,它是否被缓冲了,也许我在第二个 recv() 中得到了以前的值?

请帮忙。

你的假设没有错。它可能被缓冲。另请注意,当接收方读取数据的速度比发送方发送数据的速度快时,某些 recv 调用可能不会读取任何数据,因为发送方尚未发送任何数据。这可能是您所描述的原因。

更新:如果您计划总是 send/receive 相同数量的数据,例如一个 20 字节的数据包,其中包含您定义的 命令 ,然后您可以将 sendrecv 包装在一个循环中。该循环将一次写入(或读取)一条命令。你不能假设调用sendrecv会成功,所以你必须检查错误,正如@Joachim提到的在评论中。另一件需要注意的事情是 recv 可能读取的字节数少于指定的字节数,因此您可能需要多次读取才能接收完整的 命令 。同样适用于 send.

您可以使用select/poll机制来检查是否有新数据到达套接字并等待正确读取。您还可以通过调用 ioctl 调用来检查已到达套接字的数据量,如下所示:

{
       int size = 0;

       ioctl(socket, FIONREAD, &size);

       if(size > 0)
       {
             // do recv operation(s)
       }
}