我有一套TCP套接字保持活着(间隔1分钟),由select(2)
循环(select读取)控制。
select(2)
如果集合中的其中一个套接字发生保持活动超时返回一个错误? read(2)
返回? select()
本身不会返回错误。 [事实上,API不能以这种方式指示每个套接字错误,因为两个不同的套接字在select()
的单个调用期间可能每个都会获得一个挂起的错误。 哪一个会select()
返回?] select()
循环的每次迭代之后,您改为使用FD_ISSET宏在每个标记为可读的套接字上尝试read()
。 select()
返回,允许你立即拾取由于保持活动而导致的超时错误。 请注意,选择标记套接字进行读取并不表示有数据要读取,只是尝试读取不会被阻止。 如果套接字有一个待检错误,读取将不会被阻塞。 即使尝试处理任何数据, read(2)
和write(2)
先检索套接字上的任何挂起错误。 当对O_NONBLOCK清除的输入函数的调用不会被阻塞时,描述符应被视为准备好读取,函数是否会成功传输数据。 (该函数可能会返回数据,文件结束指示,或者是一个指示被阻塞的错误以外的错误,并且在这些情况下,这些描述符都应该被视为可以读取。)[ POSIX:select() ]
最后,返回什么错误? 至关重要的是,这取决于keepalive失败的方式。 如果另一端完全消失,您将得到 ETIMEDOUT
。 如果发生数据包传送错误,您将通过取而代之(如果保活数据包得到一个ICMP错误答复,如“主机不可达”,您将有EHOSTUNREACH
传递)。 [关于这些案例的更多细节,参见Stevens,“Unix Network Programming,vol 1”]。
select()
在FDSET
中设置一个表示哪个套接字已被触发的位。 使用FD_ISSET宏来确定哪个套接字要求服务。