socket recv无法接受服务器返回的数据信息

socket recv无法接受服务器返回的数据信息,第1张

"一直返回空"应该是服务器端没有发送数据给你,即c.recv(65535)没有接收到数据(data2没有数据),所以你print(data2)一直是空。

对策:如果data2没有数据,那么不往下处理,继续c.recv

有一种原因可能是,客户端也在向服务器端发送数据,而服务器端没有接收,导致缓冲区满,客户端并没有可以用于接收的数据,因此客户端阻塞等待。

建议用select()查看套接字的状态,来判断具体原因。

recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结。

首先阻塞接收的recv有时候会返回0,这仅在对端已经关闭TCP连接时才会发生。

而当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,socket被关掉了,后果可能就是recv永久的阻塞了。

所以一般对于阻塞的socket都会用setsockopt来设置recv超时。

当超时时间到达后,recv会返回错误,也就是-1,而此时的错误码是EAGAIN或者EWOULDBLOCK,POSIX.1-2001上允许两个任意一个出现都行,所以建议在判断错误码上两个都写上。

如果socket是被对方用linger为0的形式关掉,也就是直接发RST的方式关闭的时候,recv也会返回错误,错误码是ENOENT

还有一种经常在代码中常见的错误码,那就是EINTER,意思是系统在接收的时候因为收到其他中断信号而被迫返回,不算socket故障,应该继续接收。但是这种情况非常难再现,我尝试过一边一直在不停的发信号,一边用recv接收数据,也没有出现过。这种异常错误我附近只有一个朋友在用write的时候见到过一次,但是总是会有概率出现的,所以作为完善的程序必须对此错误进行特殊处理。

一般设置超时的阻塞recv常用的方法都如下:

while(1)

{

cnt = (int)recv(m_socket, pBuf,RECVSIZE, 0)

if( cnt >0 )

{

//正常处理数据

}

else

{

if((cnt<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR)) //这几种错误码,认为连接是正常的,继续接收

{

continue//继续接收数据

}

break//跳出接收循环

}

}

阻塞与非阻塞recv返回值没有区分,都是 <0 出错 =0 连接关闭 >0 接收到数据大小。

Linux环境下,须如下定义:struct timeval timeout = {3,0}

//设置发送超时

setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval))

//设置接收超时

setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval))


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9466115.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存