recv()未从网络获取值
我有一个典型的客户机-服务器C套接字程序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
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()
。我没有说别的。这个问题中没有关于紧急数据的内容。我不明白你的意思。