socket读写条件

概念说明

1.接收缓存区低水位标记(用于读)和发送缓存区低水位标记(用于写):
每个套接字有一个接收低水位和一个发送低水位。他们由select函数使用。
接收低水位标记是让select返回”可读”时套接字接收缓冲区中所需的数据量。对于TCP,其默认值为1。
发送低水位标记是让select返回”可写”时套接字发送缓冲区中所需的可用空间。对于TCP,其默认值常为2048

通俗的解释一下,缓存区我们当成一个大小为 n bytes的空间,那么:
接收区缓存的作用就是,接收对面的数据放在缓存区,供应用程序读。当然了,只有当缓存区可读的数据量(接收低水位标记)到达一定程度(eg:1)的时候,我们才能读到数据,不然不就读不到数据了吗。
发送区缓存的作用就是,发送应用程序的数据到缓存区,然后一起发给对面。当然了,只有当缓存区剩余一定空间(发送低水位标记)(eg:2048),你才能写数据进去,不然可能导致空间不够。

2.FIN: (结束标志,Finish)用来结束一个TCP回话.但对应端口仍处于开放状态,准备接收后续数据.

特别纠正说明:

经过测试在3.10.0-514.16.1.el7.x86_64 内核情况下SO_SNDLOWAT/SO_RCVLOWAT
默认发送和接收最低水位均为1,也就是说默认情况下低水位值可以不考虑,系统缓冲区有数据就读
有空闲就写

1
2
3
4
5
6
7
int value =0;
int v_len = sizeof(value);
getsockopt(sockfd, SOL_SOCKET, SO_SNDLOWAT, (void*)&value, &v_len);
printf("snd low at value: %d\n",value);
value = 0;
getsockopt(sockfd, SOL_SOCKET, SO_RCVLOWAT, (void*)&value, &v_len);
printf("rcv low at value: %d\n",value);

socket可读的条件

下列四个条件中的任何一个满足时,socket准备好读:
1.socket的接收缓冲区中的数据字节大于等于该socket的接收缓冲区低水位标记的当前大小。对这样的socket的读操作将不阻塞并返回一个大于0的值 {也就是返回准备好读入的数据}。我们可以用SO_RCVLOWATsocket选项来设置该socket的低水位标记。对于TCP和UDP .socket而言,其缺省值为1

2.该连接的读这一半关闭{也就是接收了FIN的TCP连接}。对这样的socket的读操作将不阻塞并返回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发送缓冲区低水位大小。写操作不会被阻塞,会直接返回写入的数据大小,SO_SNDLOWAT socket选项设置socket可写低水位大小。经过测试默认大小为1。
2.如果你已经关闭连接,或者主动fin半关闭。这种情况下socket再些将要产生SIGPIPE信号,你没有对这个信号处理的话,你的进程将会被关闭。
3.有socket异常错误待处理,这种情况下写操作并不会被阻塞会直接返回一个错误-1,想知道错误原因erron可以帮助你。

参考地址

http://blog.csdn.net/szcarewell/article/details/51227540