我正在开发客户端和服务器文件传输应用程序与UDP套接字(SOCK_DGRAM)。对于PUT方法,我有以下的执行(握手后):停止并等待文件传输协议,何时停止监听?
client
Send a packet;
if time_out
send the packet again;
else //ack received
send a new packet;
server
wait for the first packet;
send acknowledge;
while(!EOF)
Get a packet;
Send an ack;
哪里EOF如果我通过比较获得整个文件基本检查到我在握手期间发送的文件大小。
在交换过程中,数据包可能会丢失。客户端可以发送丢失的数据包。它会等待一个ACK并重新发送数据包。服务器接收数据包并发送ACK。该ACK可能会丢失,此时客户端超时并重新发送他的数据包。由于这些数据包有一个编号的序列,我们可以忽略我们多次收到的数据包。
我的混淆发生在文件传输结束。客户端刚刚发送了包含文件最后位的数据包。服务器成功接收并发送他的ACK。这个数据包会丢失。服务器应用程序现在不在while循环中,因为他将最后一位写入文件,从他的角度来看,文件传输是成功的。但是,客户端从未收到ACK,因此超时并重新发送数据包。这里应该发生什么?服务器不在侦听或正在侦听新请求,而不是数据。客户端或服务器应该在什么时候认为传输已完成并停止尝试进行通信?
我认为对于你的第一个解决方案,我会遇到同样的问题[Generals](http://en.wikipedia.org/wiki/Two_Generals%27_Problem)。客户端和服务器反转他们的角色,但不知道对方是否收到了,无论数据包是否丢失。对于你的第二种解决方案,这就是我想要做的,但现在我必须记住序列号或某种类型的会话ID,以知道数据包不属于。如果客户没有收到这些确认(在不合理的情况下,比如超过60%的掉话率),这仍然不会阻止客户继续发送。我认为3rd是最好的选择。 – 2012-03-05 23:35:54
对于第一种解决方案,您对无限回归完全正确。好点子。在实践中,我猜你会在客户离开后长时间停顿后放弃服务器。对于第二种解决方案,你是对的,你需要更多的状态。我不确定,但我怀疑TFTP PUT操作有点像这个解决方案。 – Celada 2012-03-05 23:53:46