socket - 描述符就绪条件

描述符就绪条件

我们一直在讨论等待某个描述符准备好I/O(读或写)或等待其上发生一个待处理的异常条件(带外数据)。

对于普通文件的描述符,读、写和异常条件总是返回准备好(APUE p407);

而对于套接字就绪状态的判断如下:

一、满足下列四个条件中的任何一个时,一个套接字准备好读。
  1. 监听socket”:该套接字是一个监听套接字且已完成的连接数不为0。而这样的套接字处于可读状态,是因为套接字收到了对方的connect请求,执行了三次握手的第一步:对方发送SYN请求过来,使该方监听套接字处于可读状态;通常情况下,对这样的套接字执行accept操作不会阻塞
  2. 已连接socket”:该套接字的接收缓冲区中的数据字节大于等于该套接字的接收缓冲区低水位标记的当前大小。对这样的套接字执行读操作不会阻塞并返回一个大于0的值(也就是返回准备好读入的数据)。可以用SO_RCVLOWAT套接字选项设置该套接字的低水位标记。对于TCP和UDP套接字而言,其缺省值为1,这意味着,默认情况下,只要缓冲区中有数据,那就是可读的
  3. 已连接socket”:该连接的读半部关闭(也就是接收了FIN的TCP连接)。对这样的套接字的读操作将不阻塞并返回0(也就是返回EOF),此时必须且一直会返回0
  4. 已连接socket”:其上有一个套接字错误待处理。对这样的套接字的读操作将不会阻塞并返回-1(即返回一个错误),同时把errno设置成确切的错误条件。这些待处理错误(pending error)也可通过指定SO_ERROR套接字选项调用getsockopt获取并清除。
二、下列四个条件中的任何一个满足时,一个套接字准备好写。
  1. 已连接socket/UDP socket”:该套接字发送缓冲区中的可用空间字节数大于等于该套接字的发送缓冲区低水位标记的当前大小(对于TCP的已连接socket或者UDP socket均可)。对这样的套接字的写操作将不阻塞并返回一个大于0的值(也就是返回准备好写入的数据)。可以用SO_SNDLOWAT套接字选项设置该套接字的低水位标记。对于TCP和UDP套接字而言,低水位默认值为2048,发送缓冲区默认大小为8K,这意味着,默认情况下,一个套接字连接成功后,总是可写的
  2. 已连接socket”:该连接的写半部关闭(主动发送了FIN的TCP连接)。对这样的套接字的写操作将产生SIGPIPE信号,该信号的缺省行为是终止进程;
  3. 已连接socket”:其上有一个套接字错误待处理。对这样的套接字的写操作将不会阻塞并且返回-1(即返回一个错误),同时把errno设置成确切的错误条件。这些待处理的错误也可以通过指定SO_ERROR套接字选项调用getsockopt函数来取得并清除;
  4. 使用非阻塞式connect的套接字已建立连接,或者connect已经以失败告终,即connect已经完成。

注意

  • 由一.4、二.3 可知,当某个套接字上发生错误时,它会被select标记为既可读又可写。
  • 由二.1 可知,任何UDP套接字只要发送缓冲区的可用空间字节数大于等于其发送低水位标记(默认总为该关系)就总是可写的,这是因为UDP不需要连接。
  • socket接受到普通数据或带外数据都会使select返回,但socket处于不同的就绪状态:前者处于可读状态,后者处于异常状态。

这里写图片描述

附注:

1、套接字接收区缓存(用于读)和发送区缓存(用于写):
  • 每个套接字都有一个接收区缓存和一个发送区缓存。
  • 接收区缓存:接受对方的数据到缓存区,使用缓存区和应用程序直接交互。
  • 发送去缓存:应用程序发送数据到缓存区,然后一起发给对方。
2、接收缓存区低水位标记(用于读)和发送缓存区低水位标记(用于写):
  • 每个套接字都有一个接收低水位和一个发送低水位。它们由select函数使用。
  • 接收低水位标记和发送低水位标记:允许应用进程控制在select返回可读、可写时有多少数据可读、有多大空间可用于写。
  • 接收低水位标记:让select返回”可读”时套接字接收缓冲区中所需的最少数据量。对于TCP,其默认值为1。
  • 发送低水位标记:让select返回”可写”时套接字发送缓冲区中所需的最少可用空间。对于TCP,其默认值常为2048。
  • 接收低水位标记例子:若应用进程需要至少64个字节,否则无法有效工作,那就可以将接收低水位标记设为64,以防select在低于64字节时仍然唤醒该进程。
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值