1

目前我正在实现一个简单的客户端-服务器程序,只有读/写的基本功能。

但是我注意到,例如,如果我的服务器调用 write() 来回复我的客户端,并且如果我的客户端没有相应的 read() 函数,我的服务器程序就会挂在那里。

目前我正在考虑使用一个简单的计时器来定义超时计数,然后在一定计数后断开客户端,但我想知道是否有更优雅/或标准的方式来处理此类错误?

4

2 回答 2

3

有两种通用方法可以防止服务器阻塞并通过单个服务器实例处理多个客户端:

  • 使用 POSIX 线程来处理每个客户端的连接。如果一个线程因为错误的客户端而阻塞,其他线程仍然会继续运行。如果远程客户端刚刚消失(崩溃、网络中断等),那么 TCP 堆栈迟早会发出超时信号,并且阻塞的write操作将失败并出现错误。
  • 将非阻塞 I/O 与轮询机制一起使用,例如select(2)or poll(2)。但是,使用轮询调用进行编程相当困难。网络套接字是非阻塞fcntl(2)的,如果正常write(2)read(2)在套接字上会阻塞,EAGAIN则会返回错误。您可以使用select(2)poll(2)等待套接字上发生可调整超时时间的事情。例如,等待套接字变为可写,意味着当有足够的套接字发送缓冲区空间时会通知您,例如先前写入的数据被刷新到客户端计算机的 TCP 堆栈。
于 2012-06-25T12:14:05.350 回答
1

如果客户端不再从套接字读取,它应该关闭套接字close。如果您不想这样做,因为客户端仍然可能想要写入套接字,那么您至少应该使用shutdown(fd, SHUT_RD).

这将对其进行设置,以便服务器获得EPIPE写入调用。

如果您不控制客户端...如果您未编写的随机客户端可以连接,则服务器应主动处理尝试恶意的客户端。客户端恶意的一种方法是尝试强制您的服务器挂起。您应该结合使用非阻塞套接字和您描述的超时机制来防止这种情况发生。

通常,您应该编写服务器和客户端如何通信的协议,以便服务器或客户端都不会在对方不读取时尝试写入套接字。这并不意味着您必须紧密同步它们或其他任何东西。但是,例如,HTTP 的定义方式使得任何一方都非常清楚对方是否真的希望他们在协议中的任何给定点编写任何内容。

于 2012-06-25T11:14:34.993 回答