Chinaunix首页 | 论坛 | 博客
  • 博客访问: 118395
  • 博文数量: 41
  • 博客积分: 2564
  • 博客等级: 少校
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-20 19:17
文章分类

全部博文(41)

文章存档

2009年(41)

我的朋友

分类: LINUX

2009-04-17 09:38:06

在默认的情况下,socket是blocking的。也就是说,如果某进程请求的操作不能及时完成,则会去睡觉。可以将有可能block的socket操作分为以下4个类型:

1、输入

包括read、readv、recv、recvfrom和recvmsg函数。在blocking模式下调用它们时,如果接收缓存内没有满足要求的数据可读,则进程会睡觉。

在nonblocking模式下,如果读取请求不能立即完成,则以上几个函数会直接返回,并将errno置为EWOULDBLOCK。

2、输出

包括write、writev、send、sentto和sendmsg函数。在blocking模式下调用它们时,如果发送缓存没有空间,则它们会一直阻塞。注意,UDP没有流量控制,因此没有发送缓存这一说,发送数据时,内核直接把数据报发送出去,因此blocking模式下,UDP也永远不会阻塞。

在nonblocking模式下,如果发送缓存中没有足够的空间(TCP,和SO_SNDLOWAT有关),则以上几个函数会直接返回,errno置为EWOULDBLOCK。

3、接收到来的连接

blocking模式下,如果没有连接到达,则进程会一直睡觉。

在nonblocking模式下,如果没有连接到达,则函数直接返回,errno为EWOULDBLOCK。在某些系统上使用select对listening socket进行操作时需特别注意,最好将socket设置为nonblocking模式,否则有可能出问题,详见unpv13e 16.6。

4、connect

blocking模式下,对一个TCP socket调用connect,会一直阻塞直到“3次握手”的第二个数据包到达————SYN的ACK。

在nonblocking模式下,如果连接不能立即完成,则connect会立即返回,且errno为EPROGRESS。特别的,connect在nonblocking模式下返回的错误与前3种都不同。connect返回并不代表连接动作终止,相反,“3次握手”的过程会由底层完成。那么,如何知道nonblocking模式下连接是否成功?有2种情况:

·连接可以立即完成,connect成功返回

·连接不能立即完成,connect返回错误。则此时调用select,并注册connecting socket的读/写事件,那么,在连接完成或发生错误时,select返回并标记相应的事件。


以上4个分类中,除了connect外,将socket显式的设置为nonblocking模式(O_NONBLOCK)都不是必要条件。

阅读(885) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~