TCP充分实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的包进行顺序控制,这些在UDP中都是没有的。UDP是一种没有复杂控制,提供面向无连接通信服务的一种协议。TCP是面向有连接的通信协议,只有在取人对端存在的情况下才会发送数据,从而可以控制通信流量的浪费。
知识点1:TCP通过序列号和确认应答提高可靠性:
在 TCP中当发送端的数据到达接受主机时,接收主机会返回一个已经收到消息的通知,这个消息叫做确认应答(ACK)。ACK中携带着一个信息:告诉发送端下一个应该发的包的序号。
如果发送端在一定时间内没有等到对端已经收到消息的ACK,则会认为数据已经丢失了,会进行重发,保证数据的可靠性。
发送端未收到ACK并不一定意味着数据没有被接收端接受到,也可能是接收端已经接受到,只是返回的ACK在中途丢失了。在这种情况下,发送端同样认为没有发送成功,照样会重新发送数据。
在这种情况下,接收端主机可能会连续不断地接受到相同的数据包,因此需要引入一种机制来判断在接收端是否已经收到了数据,如果收到了且又来了相同的数据,那么就没有必要重复处理了。
知识点2:重发超时如何确定:
发送端发送一个数据包之后,等待接收端返回ACK,需要确定一个时间阈值,当超过这个时间接收端仍然没有收到ACK,发送端就重新发一次刚刚发送的数据。 这个重发超时如何确定呢?
最理想的情况是找到一个最小时间,它能保证ACK一定能在这个时间内返回。然而,这个时间随着数据包途径的网络环境的不同而有变化,例如在告诉的LAN中时间会较短。即使在同一个网络中,根据不同时段的网络的拥堵程度,时间的长短也会发生变化。
TCP在每次发包时都会计算往返时间(RTT, Round Trip Time),以及其偏差(类似方差的概念)。 将RTT与偏差相加得到 重发超时的时间。
上图中的虚线表示计算出来的重发超时的时间阈值。
在BSD的 UNix以及Windows系统中,超时都是以0.5秒为单位进行控制的,都是其整数倍。不过,由于最初的数据包还不知道往返时间,所以重发超时一般设置为6s左右。
另外,数据被重发之后,如果还是收不到确认应答,则进行再次发送,此时,等待确认的应答时间将会以2倍,4倍的指数函数增长。 当达到一定的重发次数后,如果仍然收不到ACK, 就会判断网络或接收端主机发生了异常,则强制关闭连接,并通知应用层程序: 通信异常强行终止。
知识点3:TCP连接的建立与断开:
在数据通信前,客户端会先向服务器发送一个SYN(请求建立连接包),如果对端发来确认应答,则认为可以进行数据通信。
客户端在通信结束时,会向服务器发送一个FIN(请求断开连接包)。 具体的流程如下所示:
三次握手的一种理解:
客户端发送SYN,服务器接受到后就知道客户端的发送能力和自己的接受能力ok.
服务器针对SYN信号返回ACK应答,同时发送SYN信号,客户端接受到后知道自己的发送和接受能力ok, 主机的接受和发送能力ok.
然后,客户端针对服务端发送过来的syn信号进行应答,服务端接受到该应答后就知道自己的发送能力和客户端的接受能力ok.
TCP以段为单位发送数据:
TCP发送数据时,是将数据拆分成一个个的包发送的,每个包的长度称为“最大消息长度”(MSS: Maximum Segment Size)。最理想的情况是MSS的大小等于 IP层中不会被分片处理的最大数据长度,因为TCP发出的数据包,到达下一层IP层后,如果其大小大于IP层的单个数据包的最大长度,则IP层会拆它!
MSS是在建立连接时,三次握手的时候被计算出来的!(怪不得需要 三次握爪)
两端的主机在发出建立连接的请求时,会在TCP首部中写入MSS值,告诉对端自己的接口能够适应的MSS的大小,然后会在两者之间选择一个较小的值使用:
Ref:
《图解TCP/IP》--竹下隆史 6.4章节