TCP真的能保证交付吗?

时间:2017-06-17 01:09:04

标签: python sockets tcp

我正在阅读一本网络书籍,根据我所读到的有关TCP协议的内容,它确保将发送数据。我想写一些代码来进行文件传输。在开始之前,我还在Python文档中阅读了这段话:

  

“应用程序负责检查所有数据是否已经存在   发送;如果只传输了一些数据,则应用程序需要   试图传递剩余数据“

这似乎与我在网络书中读到的内容相矛盾。上面的段落说应用程序负责丢失的数据。

我可能会误解,所以我想问一些问题:

1 - 如果我必须检查数据是否已发送,那么为什么要使用TCP?

2 - 我在网络书中读到TCP进行数学运算以确保数据存在。那为什么不浪费时间使用TCP?

3- python文档没有指定缓冲区大小。一次发送缓冲区的最大大小是多少?

4-I我在网络书中读到服务器可以增加的数量 如果它知道客户端可以接收它,它可以发送的数据。这可以改变吗? 缓冲区的大小超过最大数量?

到目前为止,这是我的代码尝试:

服务器代码:

import socket
s = socket.socket()
host =  socket.gethostname()
port =  3000
s.bind((host,port))
s.listen(1)
c,addr = s.accept()
with open("Filetosend","rb") as File:
    data=  File.read(1024)
    while data:
        c.send(data)
        data =  File.read(1024)
s.close()

客户代码:

import socket
s= socket.socket()
host =  socket.gethostname()
port =  3000
s.connect((host,port))
with open("Filetowrite","wb") as File:
    data =  s.recv(1024)
    while data:
        File.write(data)
        data = s.recv(1024)
s.close()

1 个答案:

答案 0 :(得分:8)

TCP尝试保证如果数据已传递,则它是正确的并且是有序的。它使用校验和来确保数据不被破坏,并使用序列号来确保数据按顺序传递且没有间隙。它使用确认,因此发件人将知道已收到数据。

但是假设在传输过程中出现网络故障。如果在收到数据段之后但在发送回确认之前发生,则发送方将不知道已收到数据。发件人将继续尝试重新发送数据,并最终超时并向应用程序报告错误。

大多数TCP API不允许应用程序准确找出错误发生在通信的哪个位置。如果您发送了一个兆字节,并且收到错误,则可能在开始时发生,几乎没有发送任何内容,或者在发送大部分数据时结束。它甚至可能在所有数据发送后发生 - 也许只是最后一个ACK丢失了。

此外,write()系统调用通常只是将数据放入内核缓冲区。它不会等待数据发送到网络,也不会等待接收方确认它。

即使您成功关闭了连接,也无法完全确定。当您关闭连接时,发件人会向收件人发送一条消息,说明他们已完成发送数据。但是关闭连接只是在网络堆栈中排队,它不会等待其他系统确认它。

这就是为什么应用程序协议在基本TCP协议之上具有自己的确认级别的原因。例如,在SMTP协议中,客户端发送消息内容,后跟一行.以指示结束,然后等待服务器发回一个响应代码,指示消息已成功接收并正在交付或排队。 TCP的检查确保如果您收到此响应,则消息内容将保持原样发送。

关于任何协议保证完美传递所有邮件的一般能力,您应该阅读Two Generals' Problem.无论您做什么,都无法验证任何通信中所有邮件的传递,因为唯一确认最后一条消息是否已发送的方法是发送另一条消息作为回复,现在该回复是最后一条消息,需要确认。