分类: LINUX
2012-04-23 16:54:39
引起select返回socket"准备好"的条件有以下三个说明:(TCP V2的图16.52)
一、下列四个条件中的任何一个满足时,socket准备好读:
1.socket接收缓冲区中已经接收的数据的字节数大于等于socket接收缓冲区低潮限度的当前值;对这样的socket的读操作不会阻塞,并返回一个大于0的值(即:准备好读入的数据的字节数).我们可以用socket选项SO_RCVLOWAT来设置此低潮限度,对于TCP和UDPsocket,其缺省值为1;
2.连接的读这一半关闭(即:接收到对方发过来的FIN的TCP连接).对于这样的socket的读操作将不阻塞,并且返回0(即:文件结束符,FIN包体长度为0字节);
3.socket是一个用于监听的socket,并且已经完成的连接数为非0.这样的soocket处于可读状态,是因为socket收到了对方的connect请求,执行了三次握手的第一步:对方发送SYN请求过来,使监听socket处于可读状态;正常情况下,这样的socket上的accept操作不会阻塞;
4.有一个socket有异常错误条件待处理.对于这样的socket的读操作将不会阻塞,并且返回一个错误(-1),errno则设置成明确的错误条件.这些待处理的错误也可通过指定socket选项SO_ERROR调用getsockopt来取得并清除;
二、下列三个条件中的任何一个满足时,socket准备好写:
1.socket发送缓冲区中的可用空间字节数大于等于socket发送缓冲区低潮限度的当前值,且(i):socket已连接(TCP socket),或者(ii):socket不要求连接(如:UDP socket).这意味着,如果我们将这样的socket设置为非阻塞模式,写操作将不会阻塞,并且返回一个正值(如:由传输层接收的字节数).我们可以用socket选项SO_SNDLOWAT来设置此低潮限度,对于TCP和UDP socket,其缺省值一般是2048Bytes;
2.连接的写这一半关闭.对于这样的socket的的写操作将产生信号SIGPIPE;
3.有一个socket异常错误条件待处理.对于这样的socket的写操作将不会阻塞并且返回一个错误(-1),errno则设置成明确的错误条件.这些待处理的错误也可以通过指定socket选项SO_ERROR调用getsockopt函数来取得并清除;
三、如果一个socket存在带外数据或者仍处于带外标记,那么它就有异常条件待处理;
注意:一个socket出错时,它由select标记为既可读又可写;
接收和发送低潮限度的目的是:在select返回可读或可写条件之前,应用进程可以对"有多少数据可以读或有多大空间可用于写"进行控制.例如:如果我们知道除非至少64字节的数据可用,否则我们的应用进程不能完成有效的工作,那么就可以将接收低潮限度设置为64字节,以防止小于64字节的数据准备好读时,select就唤醒我们;
只要UDP socket的发送低潮限度小于发送缓冲区大小(缺省关系常常如此),由于不需要连接,这样的UDP socket总是可写的;
http://bdxnote.blog.163.com/blog/static/844423520098312111726/