【问题标题】:Check if socket still open without blocking检查套接字是否仍然打开而没有阻塞
【发布时间】:2020-08-02 00:44:02
【问题描述】:

如何检查 TCP 套接字是否仍然打开而不阻塞?

如果我使用usocket,那么如果套接字关闭,则从套接字流中读取将发出文件结束信号,否则会阻止它,这是我不想要的。我曾尝试使用(listen stream) 提前检查套接字是否会被阻塞,但(listen) 在关闭的套接字上返回nil,这在这里没有帮助。我还尝试检查(usocket::state socket),它在关闭的套接字上给出:READ,但它有时也会在打开的套接字上给出:READ,即使那里没有任何东西。我正在使用 sbcl,所以我尝试使用 (sb-bsd-sockets:socket-open-p),但这在封闭的套接字上给出了 T,也没有帮助。唯一似乎有用的命令是(wait-for-input),即在关闭的套接字上调用时它几乎会立即返回,即使给出了更长的超时时间也是如此。同时,(listen) 仍然会给出nil,这两者加起来似乎表明一个关闭的套接字。这种方式在我看来相当骇人听闻。

有没有更好的办法?

【问题讨论】:

  • 我会使用 iolib :它有 iolib:socket-connected-p 和事件处理程序(epoll/select 接口)。它还附带了一个很好的套接字教程。
  • @coredump,感谢您的提示,我会检查一下。

标签: sockets tcp common-lisp nonblocking sbcl


【解决方案1】:

这并不是一个 Lisp 问题。这是 TCP 本身固有的问题。

在 TCP 中判断连接是否仍然打开的唯一方法是尝试通过它发送数据,或者使用 TCP 的 keepalive 功能(通过套接字为您发送数据)。

Linux、Windows 和 MacOS 都有SO_KEEPALIVE 套接字选项(请参阅setsockopt(2),它实现了 TCP keepalive。还有其他相关的 sockopts,例如 TCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT,但是它们不能在操作系统之间移植,在 Lisp 中,您将面临额外的挑战,即找到 C 预处理器常量的实际值,以及为 option_value 参数提供指针。

我在 Linux 上使用 SO_KEEPALIVE 没有任何运气,也没有尝试在任何其他操作系统上使用它。

【讨论】:

  • 我了解检查连接是否已断开的唯一方法是通过它发送数据。但是,在我的情况下,连接会优雅地关闭,并且操作系统本身清楚地知道它。否则,为什么 WAIT-FOR-INPUT 会立即开始返回?我刚刚检查了lsof,它说的是 CLOSE-WAIT 而不是 ESTABLISHED,所以我似乎无法使用 USOCKET 检查它的 CLOSE-WAIT 状态。
猜你喜欢
  • 2010-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多