处理 POSIX 套接字读取() 错误
Handling POSIX socket read() errors
目前我正在实现一个简单的客户端-服务器程序,该程序仅具有读/写的基本功能。
但是我注意到,例如,如果我的服务器调用 write() 来回复我的客户端,并且如果我的客户端没有相应的 read() 函数,我的服务器程序将挂在那里。
目前,我正在考虑使用一个简单的计时器来定义超时计数,然后在某个计数后断开客户端的连接,但我想知道是否有更优雅/或标准的方式来处理此类错误?
有两种常规方法可以防止服务器阻塞和单个服务器实例处理多个客户端:
- 使用 POSIX 线程处理每个客户端的连接。如果一个线程由于错误的客户端而阻塞,其他线程仍将继续运行。如果远程客户端刚刚消失(崩溃、网络关闭等),那么 TCP 堆栈迟早会发出超时信号,并且被阻止的
write
操作将失败并出错。 - 将非阻塞 I/O 与轮询机制一起使用,例如
select(2)
或poll(2)
.但是,使用轮询调用进行编程非常困难。使用fcntl(2)
使网络套接字不阻塞,如果套接字上的正常write(2)
或read(2)
会阻塞,则会返回EAGAIN
错误。您可以使用select(2)
或poll(2)
来等待套接字上发生某些事情,并具有可调节的超时期限。例如,等待套接字变为可写,意味着当有足够的套接字发送缓冲区空间时,您将收到通知,例如,先前写入的数据被刷新到客户端计算机 TCP 堆栈。
如果客户端不再从套接字读取,它应该使用 close
关闭套接字。如果您不想这样做,因为客户端可能仍然想要写入套接字,那么您至少应该用 shutdown(fd, SHUT_RD)
关闭读取的一半。
这将对其进行设置,以便服务器在写入调用上获得EPIPE
。
如果您不控制客户端...如果您未编写的随机客户端可以连接,则服务器应处理主动尝试恶意的客户端。客户端恶意的一种方法是尝试强制服务器挂起。您应该结合使用非阻塞套接字和您描述的超时机制来防止这种情况发生。
通常,您应该编写服务器和客户端如何通信的协议,以便在另一端不读取时,服务器或客户端都不会尝试写入套接字。这并不意味着您必须紧密同步它们或任何东西。但是,例如,HTTP的定义方式是,任何一方都很清楚另一方是否真的期望他们在协议中的任何给定点写入任何内容。
相关文章:
- 分段错误 - 读取初始化指针的数组
- 在指向函数中读取变量时出现分割错误
- 读取某些文件时出现分段错误,似乎与文件大小无关
- 从对象C++中的文件读取内容时出现分段错误
- 我编写了以下代码来读取C++矩阵,然后打印其行和列.我收到此错误
- 可能的 ComputeCPP SYCL 错误读取嵌套缓冲区
- Eigen SparseLU解决错误读取访问冲突,这>m_sup_to_col被0x111011101110112
- 访问违规读取位置和错误读取字符串的错误
- libpng 错误:读取错误
- 错误读取字符到矩阵
- 分段错误读取 JSON 文件
- 斯特托克获取分段错误读取文件
- ifstream 初始化错误 - 读取字符时出错
- 读取错误-读取时无限
- 异常错误:读取位置0xDDDDDDDD时发生访问冲突
- 如何修复此错误读取位置0x00000008时发生访问冲突
- GDB:<错误读取变量>,带有 C++ 向量
- 找不到错误 读取大小 4 瓦尔格林德无效
- 分割错误读取文件
- libpng错误:读取错误(Visual Studio 2010)