【问题标题】:Handling POSIX socket read() errors处理 POSIX 套接字 read() 错误
【发布时间】:2012-06-25 11:10:58
【问题描述】:

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

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

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

【问题讨论】:

  • 什么错误?这里唯一的错误是客户端没有读取正在发送的消息。这是一个应用程序协议错误,一个程序设计错误,而不是你应该在运行时试图用绷带覆盖的东西。

标签: c++ sockets error-handling client


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    这将设置它,以便服务器在写入调用时获得EPIPE

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

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

    【讨论】:

      猜你喜欢
      • 2016-05-14
      • 1970-01-01
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-05
      • 2018-05-18
      • 1970-01-01
      相关资源
      最近更新 更多