【发布时间】:2011-09-05 15:22:21
【问题描述】:
我正在编写一个网络 C 程序,其中客户端将数据块发送到服务器,我想要 确保在我从客户端关闭套接字之前服务器已读取所有数据。我想过从服务器向客户端发送一个特殊的“ok”字符,但我想如果在服务器执行期间发生错误 程序和服务器从他身边关闭管道(例如读取系统调用失败),客户端将等待读取系统调用以获取永远不会出现的东西。关于如何解决这个问题的任何想法?
谢谢, 尼科斯
【问题讨论】:
我正在编写一个网络 C 程序,其中客户端将数据块发送到服务器,我想要 确保在我从客户端关闭套接字之前服务器已读取所有数据。我想过从服务器向客户端发送一个特殊的“ok”字符,但我想如果在服务器执行期间发生错误 程序和服务器从他身边关闭管道(例如读取系统调用失败),客户端将等待读取系统调用以获取永远不会出现的东西。关于如何解决这个问题的任何想法?
谢谢, 尼科斯
【问题讨论】:
您提出的实现对我来说听起来不错 - 如果发生错误,那是一种例外情况 - 要抓住它,您需要在读取调用中使用超时。
【讨论】:
在客户端中实现超时。等待服务器响应的一些可配置/合理的时间。如果该时间段已过,请采取相应措施。
【讨论】:
我想确保所有数据都有 在我关闭之前已被服务器 b*读取 来自客户端的套接字*.
如果您使用 TCP,请考虑:一旦您发送数据,即使您关闭套接字/退出程序,TCP 堆栈也会继续尽力发送数据。。 p>
一旦您send / write 获得数据,它就会从您手中消失。它被复制到内核缓冲区中,并在一段时间后发送。在幕后(在netinet 深处)连接不会关闭,直到所有发送的数据都得到确认/连接由于其他原因而终止。
【讨论】:
ACKTCP上的数据,它比程序员做得更好。
alternating bit protocol 是解决这个问题的一种方法。有不同的方法来实现它。
当 A 发送一条消息时,它会重新发送它 连续地,以相同的顺序 号码,直到它收到一个 来自 B 的确认,其中包含 相同的序号。当那个 发生时,A 补充(翻转) 序号和开始 发送下一条消息。
【讨论】:
无需担心何时关闭客户端的套接字。只要数据已写入套接字,之后您就可以随时关闭它。 @cnicutar 在他的回答中对此提供了很好的解释。
至于从您的服务器返回到客户端的特殊确认字符,您不必担心使用 TCP。但是,您可能希望修改数据块,使其包含一个标头,指示有多少数据。例如,数据块的前 4 个字节可以是一个长度字段,指示还有多少字节。服务器可以读取前 4 个字节,然后知道还要读取多少字节。 TCP 通信通常有这样的东西。
【讨论】:
您的客户似乎有四种可能的结果:
前三个可以在客户端直接处理。要处理第四个问题,您需要在客户端实现超时——但是您冒着过早超时的风险,而实际上服务器只是响应缓慢,而不是实际损坏。最好的办法可能是让超时时间相当长(例如 30 秒?),并确保您的服务器可靠且不会挂起。 :)
【讨论】: