Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1617741
  • 博文数量: 268
  • 博客积分: 8708
  • 博客等级: 中将
  • 技术积分: 3764
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-06 15:58
文章分类

全部博文(268)

文章存档

2014年(1)

2013年(15)

2012年(23)

2011年(60)

2010年(51)

2009年(12)

2008年(59)

2007年(47)

分类: 嵌入式

2011-08-22 13:02:33

非阻塞I/O

通常情况下套接口是阻塞的,这意味着当一个套接字函数调用不能立即完成时,进程进入睡眠,知道操作完成。可能阻塞套接口的调用分为4种。

1、输入:recv、recvfrom。当阻塞的tcp调用时,如果套接口缓冲区没有数据可读,进程将在数据到达前一直处于睡眠。同样如果一个阻塞的udp缓冲区为空,进程在下一个数据报到来前一直处于睡眠状态

而非阻塞套接口不管是否有数据都将直接返回,有数据正常返回,没数据时WSAGetLastError()会返回WSAEWOULDBLOCK。

2、输出:send、sendto。对一个tcp socket,内核从应用程序缓冲区想套接口缓冲区拷贝数据。当套接口没有空间时,进程处于睡眠,知道足够空间(windows xp下套接口的默认发送和接受缓冲区是8K,用getsockopt(m_sock, SOL_SOCKET, SO_RCVBUF,&iSize,&len)取得,也可以用setsockopt()设置缓冲区大小)。

对于非阻塞tcp套接字,如果套接字缓冲区没有空间,输出返回SOCKET_ERROR,用WSAGetLastError()得到WSAEWOULDBLOCK。直到缓冲区有空间,返回内核向套接字缓冲区拷贝的字节数。

udp套接口没有发送区,内核只是拷贝进程数据向协议栈的下层传递,加上udp与ip的头部。因此一个阻塞udp的socket的输出操作不会阻塞。

3、接受外来连接:accept。如果一个阻塞套接口调用accept,而且没有新的连接,进程进入睡眠。在非阻塞接口调用accept,accept立即返回(有点疑义,后面补上)

4、初始化连接:tcp的connect。(udp的connect并不建立真实连接,只是内核保存了对方ip和端口)tcp的连接建立包括3次握手过程,而且客户端在接收到其SYN的ACK前不会返回。就是说tcp connect至少会阻塞一次往返时间(RTT)。

而在一个非阻塞的tcp套接口上调用connect,一般不能马上建立连接,返回SOCKET_ERROR,WSAGetLastError()得到WSAEWOULDBLOCK错,但是connect的三次握手继续进行。需要注意的是client与server在同一台电脑上时,连接可以马上建立。一般情况下需要注册通知事件:

  • select检查socket是否可写
  • WSAEventSelect的FD_CONNECT(这个没用过)

简单讲,非阻塞socket一般与select模型一起使用。

gethostbyname  does not return until it has succeeded or failed in resolving ;
 
the connect does not return until it has connected;
 
the recv calls do not return until they have received data or a close;
 
and the send call does not return until it has at least flushed its output to the
kernel’s write buffers.
 
 
阅读(1243) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~