如何检查TCP套接字是否仍然打开而没有阻塞?
如果我使用的是usocket
,则如果套接字已关闭,则从套接字流中读取将表示文件已结束,但否则将阻止它,这是我所不希望的。我尝试使用(listen stream)
预先检查套接字是否将被阻塞,但是(listen)
在关闭的套接字上返回nil
,这在这里无济于事。我也尝试过检查(usocket::state socket)
,它在关闭的套接字上给出:READ
,但是有时即使在没有打开的套接字上也给出:READ
。我正在使用sbcl,因此我尝试使用(sb-bsd-sockets:socket-open-p)
,但这在封闭的套接字上显示T
,也无济于事。似乎唯一有用的命令是(wait-for-input)
,即在封闭套接字上调用时,即使给出了更长的超时时间,它也将几乎立即返回。同时,(listen)
仍将为nil
,并且加起来似乎表示插座已闭合。这种方式对我来说似乎有点黑。
还有更好的方法吗?
这不是Lisp问题。这是TCP本身固有的问题。
TCP中判断连接是否仍处于打开状态的唯一方法是尝试通过该连接发送数据,或者使用TCP的keepalive功能(该功能通过套接字为您发送数据)。
Linux,Windows和MacOS都具有SO_KEEPALIVE
套接字选项(请参阅setsockopt(2)
,该选项实现了TCP keepalive。还有其他关联的sockopt,例如TCP_KEEPIDLE
,TCP_KEEPINTVL
和TCP_KEEPCNT
,但它们在操作系统之间不可移植,在Lisp中,您将面临另外一个挑战,即查找C预处理程序常量的实际值,并提供option_value
参数的指针。
我在Linux上使用SO_KEEPALIVE
并没有任何运气。