目前我正在实现一个简单的客户端-服务器程序,只有读/写的基本功能。
但是我注意到,例如,如果我的服务器调用 write() 来回复我的客户端,并且如果我的客户端没有相应的 read() 函数,我的服务器程序就会挂在那里。
目前我正在考虑使用一个简单的计时器来定义超时计数,然后在一定计数后断开客户端,但我想知道是否有更优雅/或标准的方式来处理此类错误?
目前我正在实现一个简单的客户端-服务器程序,只有读/写的基本功能。
但是我注意到,例如,如果我的服务器调用 write() 来回复我的客户端,并且如果我的客户端没有相应的 read() 函数,我的服务器程序就会挂在那里。
目前我正在考虑使用一个简单的计时器来定义超时计数,然后在一定计数后断开客户端,但我想知道是否有更优雅/或标准的方式来处理此类错误?
有两种通用方法可以防止服务器阻塞并通过单个服务器实例处理多个客户端:
write
操作将失败并出现错误。select(2)
or poll(2)
。但是,使用轮询调用进行编程相当困难。网络套接字是非阻塞fcntl(2)
的,如果正常write(2)
或read(2)
在套接字上会阻塞,EAGAIN
则会返回错误。您可以使用select(2)
或poll(2)
等待套接字上发生可调整超时时间的事情。例如,等待套接字变为可写,意味着当有足够的套接字发送缓冲区空间时会通知您,例如先前写入的数据被刷新到客户端计算机的 TCP 堆栈。如果客户端不再从套接字读取,它应该关闭套接字close
。如果您不想这样做,因为客户端仍然可能想要写入套接字,那么您至少应该使用shutdown(fd, SHUT_RD)
.
这将对其进行设置,以便服务器获得EPIPE
写入调用。
如果您不控制客户端...如果您未编写的随机客户端可以连接,则服务器应主动处理尝试恶意的客户端。客户端恶意的一种方法是尝试强制您的服务器挂起。您应该结合使用非阻塞套接字和您描述的超时机制来防止这种情况发生。
通常,您应该编写服务器和客户端如何通信的协议,以便服务器或客户端都不会在对方不读取时尝试写入套接字。这并不意味着您必须紧密同步它们或其他任何东西。但是,例如,HTTP 的定义方式使得任何一方都非常清楚对方是否真的希望他们在协议中的任何给定点编写任何内容。