40. socket 就绪条件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Function_Dou/article/details/89949820

在实现网络通信前, 先来了解一下socket套接字什么时候就绪(可读可写). 第一次学习socket只需要明白我用红色标记的条件就行.


缓冲区

每个套接字接收区缓存 (用于读) 和发送区缓存 (用于写) :

  • 接收区缓存: 接收数据, 从内核缓冲复制到用户应用程序数据缓冲区.
  • 发送去缓存: 用户应用程序数据缓冲区复制到内核缓冲区, 等待发送.

每个套接字都有接收缓存区低水位标记(用于读)和发送缓存区低水位标记(用于写):

  • 接收低水位: 可读时套接字接收缓冲区中所需的最少数据量. 对于TCP, 其默认值为1.
  • 发送低水位: 可写时套接字发送缓冲区中所需的最少可用空间. 对于TCP, 其默认值常为2048.

可以修改接收缓冲区的低水位来保证不用频繁的调用读, 等累计到一定的量在一次性读. 这样就可以减少读的次数. 像libevent就设置了用户的低水位, 高水位.


socket可读

  1. 监听socket上有新的连接请求. 因为套接字收到了对方的connect请求, 执行了三次握手的第一步: 对方发送SYN请求过来, 使该方监听套接字处于可读状态; 通常情况下, 对这样的套接字执行accept操作不会阻塞.
  2. 已连接socket. socket内核接收缓存区中的字节数大于或等于其低水位标记SO_RCVLOWAT, 此时可以无阻塞地读该socket, 并且读操作返回的字节数大于0. 对于TCP和UDP套接字而言, 其缺省值为1, 默认情况下, 只要缓冲区中有数据, 那就是可读的.
  3. socket通信对端关闭连接[1], 此时对该socket读操作将返回0.
  4. socket上有未处理的错误[2]. 对这样的套接字的读操作将不会阻塞并返回-1(即返回一个错误), 同时把errno设置成确切的错误条件. 此时我们可以使用getsockopt来读取和清除该错误. select能处理的异常情况只有一种: socket上接收到带外数据

socket可写:

  1. 已连接socket. socket内核发送缓冲区中的可用字节数大于或等于其低水位标记SO_SNDLOWAT. 此时我们可以无阻塞写该socket, 并且写操作返回的字节数大于0. 对于TCP和UDP套接字而言, 低水位默认值为2048, 发送缓冲区默认大小为8K. 默认情况下, 一个套接字连接成功后,总是可写的.

  2. socket写操作被关闭. 对写操作被关闭的socket执行写操作将触发一个SIGPIPE信号, 该信号的缺省行为是终止进程.

  3. socket使用非阻塞connect连接成功或者失败(超时)[3]. 使用非阻塞式connect的套接字已建立连接, 或者connect已经以失败告终, 即connect已经完成.

  4. socket上有未处理的错误[2]. 对这样的套接字的写操作将不会阻塞并且返回-1(即返回一个错误), 同时把errno设置成确切的错误条件. 此时我们可以使用getsockopt来读取和清除该错误. select能处理的异常情况只有一种: socket上接收到带外数据.

注意 : 当socket错误时, 此时既可读也可写.


小结

  • 了解缓冲区
  • socket读写时期

猜你喜欢

转载自blog.csdn.net/Function_Dou/article/details/89949820