Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
recv()未从网络获取值_C_Linux_Sockets_Tcp_Network Programming - Fatal编程技术网

recv()未从网络获取值

recv()未从网络获取值,c,linux,sockets,tcp,network-programming,C,Linux,Sockets,Tcp,Network Programming,我有一个典型的客户机-服务器C套接字程序 SERVER: if(ndp.cmd == 11) { //ack1 = 0; puts("Query Command for Light 2"); pthread_mutex_lock(&lock); // ..Some critical stuff

我有一个典型的客户机-服务器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
服务器:
如果(ndp.cmd==11)
{   
//ack1=0;
puts(“灯光2的查询命令”);
pthread_mutex_lock(&lock);
//…一些重要的东西
pthread_mutex_unlock(&lock);
printf(“ID:%d,级别:%d\n”,new.address,new.Level);
ack1=new.level;//此结果在服务器上显示正确
ack1=htonl(ack1);
发送(client_sock,&ack1,sizeof(ack1),0);
}
客户:
printf(“查询实际液位灯2\n”);
dp.id=2;dp.cmd=11;dp.active=0;dp.level=0;dp.group=0;
if(发送(sock,&dp,sizeof(dp),0)<0){put(“发送失败”);}
睡眠(1);
ret=recv(sock,&level1,sizeof(level1),0);
printf(“接收的字节数:%d\n”,ret)//总是给4分
fflush(stdout);
printf(“光照级别%x\n”,ntohl(级别1))//打印0(不正确)
fflush(stdout);
睡眠(5);
printf(“查询实际液位灯2\n”);
dp.id=2;dp.cmd=11;dp.active=0;dp.level=0;dp.group=0;
if(发送(sock,&dp,sizeof(dp),0)<0){put(“发送失败”);}
睡眠(1);
ret=recv(sock,和level2,sizeof(level2),0);
printf(“接收的字节数:%d\n”,ret);//总是给4分
fflush(stdout);
printf(“光照级别%x\n”,ntohl(级别2))//这将打印正确的值
fflush(stdout);
关闭(袜子);
预期产出:
亮度等级32(十六进制值为50);
光级32
实际产量:
灯光等级0
光级32
所以问题是在相同的请求上,客户机没有收到来自服务器的第一次发送,但next recv()给出了正确的值

为什么来自1st recv()的数据会丢失,它会被缓冲,也许我会在2nd recv()中得到上一个值


请帮忙。

你的假设没有错。它可以被缓冲。还请注意,当接收方读取数据的速度快于发送方发送数据的速度时,一些
recv
呼叫可能不会读取数据,因为发送方尚未发送任何数据。这可能就是你所描述的原因


更新:如果您计划始终发送/接收相同数量的数据,例如包含您定义为命令的20字节数据包,那么您可以将
发送
接收
打包成一个循环。此循环将一次写入(或读取)单个命令。不能假设调用
send
recv
会成功,因此必须检查错误,如@Joachim在评论中所述。另一件需要注意的事情是,
recv
读取的字节数可能少于指定的字节数,因此您可能需要多次读取才能接收完整的命令。这同样适用于
send

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

{
       int size = 0;

       ioctl(socket, FIONREAD, &size);

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

您需要检查
recv
实际返回的内容!如果连接关闭了怎么办?如果当前没有要读取的内容(因为您使用了
MSG\u DONTWAIT
标志),该怎么办?此检查recv()<4表示我没有收到完整的整数,对吗?但是这个检查总是成功的,所以我总是得到4个字节。但是如果它失败了,你不知道它为什么失败。它可能很简单,因为数据还没有到达,所以
recv
返回
-1
并将
errno
设置为
eWoldBlock
,但由于
MSG_DONTWAIT
标志,它实际上不是一个错误。此外,请使用预期和实际输出更新您的问题。对于您正在发送的数据,您的发送和接收数据方法似乎可能会失败。您应该考虑使用SELECT/PORM机制进行顺序读/写套接字操作。确实更新了一些关于您应该考虑的细节。如果每次需要发送/接收任意数量的数据,则需要一种方法来标识每个命令的开始/结束;两个地方。我得到了同样的结果。您可能在没有设置适当标志的情况下误用了select函数。尝试使用poll函数,它类似于select,但在某些方面使用起来更方便。在正确使用此系统调用并提出问题之前,请阅读并了解此系统调用。这里的
ioctl()
是没有意义的。当
recv()
已经告诉您它接收到了多少字节时,这是一个额外的系统调用。在
ioctl()
recv()之间可能会有更多的字节。
你对我的另一个答案做了同样的评论,我也在那里回答了你。尽管在这个问题上实现是不同的,但也没有必要使用recv call。它可能是套接字读取操作。我要指出的是,使用轮询机制(而不是在任意套接字操作之间使用睡眠),这种方法将更加方便。如果要使用读取系统调用读取套接字,则使用ioctl检查套接字中等待检索的紧急数据量将非常有用。必须使用
read()
recv()
。我没有说别的。这个问题中没有关于紧急数据的内容。我不明白你的意思。