我有一组带有keep-alive(间隔1分钟)的TCP套接字,由一个select(2)
循环(选择读取)控制。
- 如果一组套接字中的其中一个发生了keep-alive超时,
select(2)
会返回错误吗? read(2)
会返回哪个错误?
我有一组带有keep-alive(间隔1分钟)的TCP套接字,由一个select(2)
循环(选择读取)控制。
select(2)
会返回错误吗?read(2)
会返回哪个错误?select()
本身不会返回错误,即使其中一个套接字已发生错误。[事实上,API无法通过这种方式指示每个套接字的错误,因为在单次select()
调用期间,两个不同的套接字都可能获得待处理错误。那么select()
会返回哪个呢?]select()
循环迭代后,您可以使用FD_ISSET宏尝试对标记为可读的每个套接字执行read()
。select()
返回,从而允许您立即获取由于保持活动而超时的错误。请注意,select将套接字标记为可读并不表示有数据可供读取,而只是表示读取尝试不会阻塞。如果套接字有待处理错误需要检索,则读取操作不会阻塞。在尝试处理任何数据之前,read(2)
和write(2)
首先检索套接字上的任何待处理错误。当使用O_NONBLOCK清除的输入函数调用不会阻塞时,描述符将被视为准备好读取,无论函数是否成功传输数据。(该函数可能返回数据,文件结束指示或错误,而不是表示它被阻塞,并且在每种情况下,描述符都应视为准备好读取。)[POSIX:select()]
最后,会返回什么错误?关键在于,它取决于保持活动失败的方式。如果另一端完全消失,您将收到 ETIMEDOUT
。如果出现数据包传递错误,则将其传递(因此,如果保持活动数据包收到ICMP错误回复,例如“主机不可达”,则会传递EHOSTUNREACH
)。[有关这些情况的更多详细信息,请参见Stevens的“Unix网络编程,第1卷”。]
select
确实会返回已设置为可读的套接字,并且read
无法通知您套接字已死亡。这正是select
设置套接字可读的原因:以便您知道发生了什么并可以处理错误。最后,即使没有数据可读,select
正确地将套接字标记为可读:手册给出了更精确的描述,“如果读取不会阻塞,则选择标记为读取”。返回错误是即时的(不会阻塞),因此符合文档(请阅读!)。 - Nicholas Wilson