把数据读到buffer里后recv函数才会返回

时间:2022-04-10 04:41:48

梗阻模型 int recv(
SOCKET s,
char* buf,
int len,
int flags
);
  int send(
SOCKET s,
const char* buf,
int len,
int flags
);
 

这种方法最为大家熟悉,Socket默认的就是梗阻模式。

在recv的时候,Socket会梗阻在那里,直到连接上有数据可读,把数据读到buffer里后recv函数才会返回,不然就会一直梗阻在那里。

如果在主线程中被梗阻,而数据迟迟没有过来,那么措施就会被锁死。这样的问题可以用多线程解决,但是在有多个套接字连接的情况下,这不是一个好的选择,扩展性很差,而且也容易有锁的问题。线程过多,也导致上下文切换过于频繁,导致系统变慢,而且大部分线程是处于非勾当状态的话,这就大大浪费了系统的资源。

设置为非梗阻: int ioctlsocket(
IN SOCKET s,
IN long cmd,
IN OUT u_long FAR * argp
);
#define FIONBIO /* set/clear non-blocking i/o */
 

挪用ioctlsocket函数设置FIONBIO为1就转为非梗阻模式。

当recv和send函数没有筹备好数据时,函数不会梗阻,当即返回错误值,用GetLastError返回的错误码为WSAEWOULDBLOCK,中文解释为“无法当即完成一个非否决性套接字的操纵”。

固然,这里你可以用非梗阻模拟梗阻模式,就是用while循环不竭挪用recv,直到recv返回告成为止。这样的效率也不高,但好处在于你能在没接收到数据时,有空进行其他操纵,或者直接Sleep。

把套接字设置为非梗阻模式,即报告系统:在挪用Windows socket API时,不让主调线程睡眠,而让函数当即返回。好比在挪用recv函数时,即使此时接受缓冲区没有数据,也不会导致线程在recv处期待,,recv函数会当即返回。如果没有挪用告成函数会返回WSAEROULDBLOCK错误代码。为了接收到数据必需循环挪用recv,这也长短梗阻与梗阻模式的主要区别。

unsigned long ul=1; int ret; s=socket(AF_INET,SOCK_STREAM,0); ret=ioctlsocket(s,FIONBIO,(unsigned long *)&ul);//设置成非梗阻模式。 if(ret==SOCKET_ERROR)//设置掉败。 { }