假设客户端发送了100个字节的数据,但不知何故服务器只收到90个字节。我该如何处理这个案子?如果服务器调用while循环中的“read”函数检查总接收数据,那么服务器将永远等待最后10个字节的包。
此外,客户端可能会在数据传输过程中断开连接。在这种情况下,服务器将永远等待,直到它收到所有不会到达的数据..
我正在使用tcp,但在现实世界的网络环境中,这种情况可能会发生。提前谢谢......
答案 0 :(得分:1)
您必须仔细检查read
的返回值。它可以返回任何三个的东西:
正数,表示读取了一些字节。
为零,表示另一端已正常关闭连接。
-1,表示发生了错误。 (如果套接字是非阻塞的,那么错误EAGAIN或EWOULDBLOCK意味着连接仍然打开,但现在没有数据准备好,所以你需要等到epoll
说有更多数据供你使用。 )
如果你的代码没有检查这三件事中的每一件并以不同的方式处理它们,那么它几乎肯定会被打破。
这些涵盖了您询问的所有情况,例如客户端发送90个字节然后关闭或粗暴地断开连接(因为read()将返回0或-1表示这些情况。)
如果您担心客户端可能发送90个字节然后再发送,并且从不关闭连接,那么您必须实现自己的超时。为此,你最好的选择是非阻塞套接字,并在select()/ poll()/ epoll()上设置超时,如果连接空闲时间过长则抛弃连接。
答案 1 :(得分:1)
在收到所需的字节数之前,不要在循环中调用read()
函数。相反,您将套接字设置为非阻塞并在循环中调用read()
函数,直到它返回0
(表示流结束)或错误。
在正常情况下,循环将以read()
结束返回-1,errno
设置为EAGAIN
。这表示连接尚未关闭,但当前没有更多数据可用。此时,如果您还没有足够的客户端数据,只需保存做以后的数据,然后返回主epoll()
循环。
如果剩余数据到达时,套接字将以epoll()
的形式返回,您将read()
其余数据,检索保存的数据并处理所有数据。< / p>
这意味着您需要在每个套接字数据结构中存储空间来存储读取但未处理的数据。
答案 2 :(得分:0)
TCP连接是在基于数据包的网络之上分层的双向流。通常只读取对方发送的部分内容。你必须循环阅读,直到你有一个完整的消息。为此,您需要一个应用程序级协议 - 消息的类型,结构和语义 - 您在TCP(FTP,HTTP,SMTP等)之上使用这些协议。
要回答问题的特定第二部分 - 将EPOLLRDHUP
添加到epoll(7)
个事件集中,以便在连接断开时收到通知。
答案 3 :(得分:0)
除了caf所说的,我建议只订阅EPOLLRDHUP,因为这是确定连接是否已关闭的唯一安全方法(read()== 0不可靠,因为caf也提到了这一点,在出现错误时可能是真的)。 EPOLLERR 始终订阅,即使您没有特别要求它。正确的行为是在EPOLLRDHUP的情况下使用close()关闭连接,甚至可能在设置EPOLLERR时关闭连接。
有关详细信息,我在此处给出了类似的答案:epoll_wait() receives socket closed twice (read()/recv() returns 0)