当前位置: 首页 > 科技观察

五分钟带你看懂TCP协议(图文并茂)

时间:2023-03-12 18:57:53 科技观察

TCP是互联网的核心协议之一。本文介绍其基础知识。一、TCP协议的作用互联网由一组协议组成。TCP只是一层,有自己的分工。(图片说明:TCP是以太网协议和IP协议的上层协议,也是应用层协议的下层协议。)底层以太网协议(Ethernet)规定了电子信号如何由数据包组成(packets),解决了子网内部点对点通信的问题。(图片说明:以太网协议解决了局域网的点对点通信。)但是以太网协议无法解决多个局域网之间如何通信,由IP协议来解决。(图片说明:IP协议可以连接多个局域网。)IP协议定义了自己的一套地址规则,称为IP地址。它实现了路由功能,允许一个局域网中的主机A向另一个局域网中的主机B发送消息。(图片说明:路由器是基于IP协议的,局域网是通过路由器连接起来的。)路由的原理很简单。市面上的路由器背面都有很多网口,需要接多根网线。路由器内部有一张路由表,规定A网段的IP地址从1号出口出,B网段的IP地址从2号出口出。通过这组“导向牌”,数据包的转发实现了。(图片说明:本机的路由表指明了不同IP目的地的数据包应该发送到哪个网口(接口)。)IP协议只是一种地址协议,不保证数据包的完整性。如果路由器丢包(比如缓冲区满了,新进来的数据包会丢失),就需要找出丢失的是哪个包,以及如何重发该包。这取决于TCP协议。简单的说,TCP协议的作用就是保证数据通信的完整性和可靠性,防止丢包。二、TCP数据包的大小。以太网数据包(packet)的大小是固定的,最初是1518字节,后来增加到1522字节。其中,1500字节为净荷,22字节为头信息。IP数据包在以太网数据包的有效载荷里面,它也有自己的头信息,至少需要20字节,所以IP数据包的有效载荷最多为1480字节。(说明:IP数据包在以太网数据包内,TCP数据包在IP数据包内。)TCP数据包在IP数据包的有效载荷内。它的头部信息也需要最少20个字节,所以一个TCP数据包的最大负载是1480-20=1460个字节。由于IP和TCP协议通常具有额外的标头信息,因此实际的TCP有效载荷约为1400字节。因此,一条1500字节的消息需要两个TCP数据包。HTTP/2协议的一大改进是压缩了HTTP协议的头部信息,这样一个HTTP请求就可以放在一个TCP包中,而不是分成多个,提高了速度。(图片说明:以太网数据包的负载为1500字节,TCP数据包的负载为1400字节左右。)3、TCP数据包的序列号(SEQ)为1400字节/包,所以一个一次发送大量数据。它必须分成多个包。比如一个10MB的文件需要发送7100多个数据包。发送时,TCP协议对每个数据包进行编号(序号,简称SEQ),以便接收方按顺序恢复。在数据包丢失的情况下,也可以知道丢失了哪个数据包。第一个数据包的编号是一个随机数。为了便于理解,这里简称为一号包。假设这个数据包的载荷长度是100字节,可以推导出下一个数据包的编号应该是101。即每个数据包可以得到两个数:自己的编号,和下一个数据包的编号。接收方因此知道应该以什么顺序将它们恢复为原始文件。(图片说明:当前包的编号是45943,下一个包的编号是46183,可以看出这个包的payload是240字节。)4.组装TCP包收到TCP包后,assemble和restore是由操作系统完成的。应用程序不直接处理TCP数据包。对于应用程序,不关心数据通信的细节。除非线路异常,否则总是收到完整的数据。应用程序需要的数据放在TCP数据包中,有自己的格式(如HTTP协议)。TCP没有提供任何机制来指示原始文件的大小,这是由应用层协议指定的。例如,HTTP协议有一个头信息Content-Length,表示消息体的大小。对于操作系统来说,就是不断的接收TCP数据包,并按顺序组装起来,数据包不多。操作系统不会处理TCP数据包中的数据。一旦组装好TCP数据包,它们就会被传递给应用程序。TCP数据包中有一个端口(port)参数,用于指定传输给监听端口的应用程序。(图片说明:系统根据TCP包中的端口,将组装好的数据传输给相应的应用程序。上图中,21端口是FTP服务器,25端口是SMTP服务,80端口是Web服务器。)应用程序接收组装后的原始数据。以浏览器为例,它会根据HTTP协议的Content-Length字段正确读取一段数据。这也意味着一个TCP通信可以包含多个HTTP通信。5.慢启动和ACK服务器发送数据包,当然是越快越好,最好一次全部发送。但是,如果发送速度过快,则有丢包的可能。低带宽、过热的路由器、缓冲区溢出和许多其他因素都可能导致数据包丢失。线路不好,送的越快,输的越多。理想状态是在线路允许的情况下达到最高速率。但是我们怎么知道对方线路的理想速率是多少呢?答案是慢慢来。为了达到效率和可靠性的统一,TCP协议设计了一种慢启动(slowstart)机制。一开始慢速发送,然后根据丢包情况调整速率:如果没有丢包,发送速度会加快;如果数据包丢失,发送速度会降低。(ConstantTCP_INIT_CWND)在Linux内核中设置。刚开始通信时,发送方一次发送10个数据包,即“发送窗口”的大小为10。然后停下来,等待接收方确认后再继续发送。默认情况下,接收方每收到两个TCP数据包就会发送一个确认。“confirmation”的英文单词是acknowledgment,所以这条确认信息就简称为ACK。ACK携带两条信息。Expecttoreceivethenumberofnextdatapacketreceiverthereceivingwindowremainingcapacity有了这两条信息,再加上自己已经发送的数据包的最新编号,发送方就可以猜出大概的接收速度了receiver,从而降低或增加发送速率。这称为“发送窗口”,这个窗口的大小是可变的。(图片说明:每个ACK携带下一个数据包的编号,以及接收窗口的剩余容量,双方都发送ACK。)注意,由于TCP通信是双向的,所以双方都需要发送ACK。双方的窗口大小很可能不同。而ACK就是几个简单的字段,通常和数据结合在一起,放在一个数据包中发送。(图片说明:上图中有4次通信,第一次通信主机A发送给主机B的包号为1,长度为100字节,所以第二次通信中主机B的ACK号为1+100=101,第三次通信主机A的包号也是101。同理,第二次通信主机B发送给主机A的包号为1,长度为200字节,所以第三次通信主机A的ACK为201,第四次通信主机B的包号也是201。)即使是带宽大、线路好的连接,TCP总是从10个数据包开始慢慢尝试,一段时间后达到最高传输速率。这就是TCP慢启动。6、数据丢包的处理TCP协议可以保证数据通信的完整性。这是如何运作的?如前所述,每个数据包都携带下一个数据包的编号。如果没有收到下一个数据包,ACK号不会改变。比如现在收到了4号包裹,但是没有收到5号包裹。ACK会被记录下来,期待收到5号包。一段时间后,收到5号包,下一轮ACK会更新编号。如果仍然没有收到5号包,但是收到了6号或者7号包,那么ACK中的数字不会改变,一直显示5号包。这会导致大量具有重复内容的ACK。如果发送端发现连续收到了三个重复的ACK,或者超时后没有收到任何ACK,则确认丢包,即5号包丢失,然后重新发送该包。通过这种机制,TCP保证不会丢失任何数据包。(图片说明:HostB没有收到100号数据包,会不断发送相同的ACK,触发HostA重发100号数据包。)