【问题标题】:Network packet loss causes client code to act strange网络丢包导致客户端代码行为异常
【发布时间】:2019-04-09 10:40:13
【问题描述】:

我面临一些问题,我需要一些帮助才能找到解决此问题的最佳方法。

问题来了——

我有一个正在运行的服务器代码,它有一个正在侦听接受新传入连接的套接字。

然后我尝试启动一个客户端,该客户端也有一个正在侦听接受新传入连接的套接字。

客户端代码首先在侦听套接字文件描述符上接受一个新连接,然后为 I/O 获取一个新的套接字文件描述符。

服务器做同样的事情并为 I/O 获取一个新的套接字文件描述符。

注意:客户端尚未完全启动。它需要从服务器接收一些字节并发送一些字节才能启动。

然后我介绍了 TCP/IP 网络连接上的一些数据包丢失。这会导致某些错误(例如:客户端进程中的 recv() 系统调用没有看到接收到的字节,然后关闭客户端的套接字连接并关闭关联的新套接字文件描述符。)但是,这会离开客户端进程挂起,因为 FD_SET 中有其他描述符,但它们都没有准备好 I/O。所以 pselect() 不断返回 0 个文件描述符,为 I/O 做好准备。客户端在启动之前需要通过连接发送和接收某些字节。

我的问题更多的是我应该在这里做什么?

当我在 accept() 系统调用期间创建新的套接字连接时,我对 SO_KEEPALIVE 选项进行了研究。但我认为这不会解决我的问题,特别是如果网络数据包丢失正在进行的话。

如果我意识到没有准备好 I/O 的文件描述符并且永远不会,我应该在这里终止客户端进程吗?有没有更好的方法来解决这个问题?

【问题讨论】:

  • 如果您的客户端和服务器都只接受传入连接,那么是谁或什么发起了这些连接?
  • @JeremyFriesner - 代码创建父套接字以侦听服务器和客户端代码中的任何传入连接。当该套接字上有任何内容时,代码使用 accept() 系统调用来创建新的套接字连接。希望这会有所帮助。
  • 通常客户端会连接到服务器。这里会发生这种情况吗? (如果不是,那么我会将这两个程序都描述为“服务器”)
  • 是的,你可以这么说。这两个进程也在本地主机上。

标签: sockets client-server tcp-ip


【解决方案1】:

如果我没看错的话,问题的核心是:“当作为其功能核心的 TCP 连接中断时,您的客户端程序应该怎么做?”

这个问题的答案实际上是一个偏好问题——在这种情况下,您希望您的客户端程序做什么?或者换句话说,您的用户会发现什么行为最有用?

在我自己的许多客户端程序中,我都包含这样的逻辑,即如果与服务器的 TCP 连接断开,客户端将自动尝试创建与服务器的新 TCP 连接,从而恢复其连接性和有用的功能尽快。

另一个明显的选择是在连接断开时让客户端退出;也许带有某种错误指示,以便用户知道客户离开的原因。 (可能是一个询问用户是否要尝试重新连接的错误对话框?)

SO_KEEPALIVE 在这种情况下可能对你没有多大帮助,顺便说一下——尽管它的名字,它的目的是帮助程序更及时地发现 TCP 连接已经丢失,不要 更努力地保持 TCP 连接不丢失。 (而且它甚至不能很好地达到这个目的,因为在许多 TCP 堆栈中,每小时只发送一个 keepalive 数据包,左右,这意味着即使启用了SO_KEEPALIVE,它也可能需要很长时间才能启动程序收到反映网络连接丢失的错误消息)

【讨论】:

  • 这是有道理的。理想情况下,我想杀死客户端进程(或者我认为)。杀死客户端进程将导致服务器进程在从客户端请求字节时没有收到任何字节,并意识到它已经消失,然后继续关闭自己的套接字文件描述符。我认为这将是理想的。必须再次重试套接字连接的问题是,正如我所提到的,网络丢失可能正在持续。因此,accept() 很有可能不会接受新连接。
  • 如果您关心的只是确保两个进程中的每一个都尽早意识到 tcp 连接已断开,那么最好的方法就是让它们每个 send() 一个虚拟定期通过 tcp 套接字传输一个或两个字节。这将强制 tcp 堆栈尝试发送数据包,这反过来又会导致它注意到它们没有被确认,并在一两分钟内出错。
  • 出错并清理套接字连接是可能的。但是客户端进程(部分启动但未完全启动)应该随它而去。我想知道在关闭其套接字连接后向客户端发送 SIGTERM 是否是个好主意。
  • 如果您希望客户端离开,只需将其编程为自行退出/退出。我认为在客户端之外实现该逻辑没有任何优势。
猜你喜欢
  • 2023-03-24
  • 2014-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-04-29
  • 2014-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多