深入理解TCP协议

  TCP是面向连接的传输层层协议,可以为应用层提供可靠的数据传输服务。所谓的面向连接并不是真正意思上的连接,只不过是在发送数据之前,首先得相互握手,也就是说接收方知道你要发数据给它了。而UDP是面向无连接的传输层协议,并不提供可靠的数据传输。有一个很恰当的比喻:UDP传输就类似于写信,接收方事先并不知道你要写信给他;而TCP传输就像是打电话,必须等对方按了接听键你才能更他通话。

  那么TCP又是如何来实现面向连接和可靠性服务的??在讨论TCP的可靠数据传输之前,我们先看看最简单的传输层服务UDP。

1、UDP

  

  源端口号/目的端口号:同TCP首部中端口号的作用相同

  首部长度:报文段中的字节数(首部加数据)。

  校验和:差错检测,用于确定当UDP报文段从源到达目地移动时,其中的比特是否发生了变化。

  检验和如何计算??

  包括三部分:UDP伪首部、UDP首部、UDP数据部分。伪首部如下所示:

  

  其中,协议字段:TCP为6,UDP为17,UDP长度即为UDP(包括UDP头和数据部分)的总长度。

首先把UDP伪首部添加到UDP的前面,然后把UDP首部中的检验和字段填0,把所有的位划分成16位的字把所有16位的字相加,如果遇到进位,则将高于16字节的进位部分的值加到最低位上,如:1011 1011 0101 1110 +1111 1100 1110 1100 = 1 1011 1000 0100 1010那么把1 1011 1000 0100 1011最高位的1加到最低位上得1011 1000 0100 1011将所有字相加得到的结果为一个16位的数,将该数取反即为检验和字段 

  从UDP的首部我们就可以看到,UDP是一个很简陋的传输层协议,只负责从发送端的应用层接收数据,封装层UDP报文段,然后交给下层发送到接收端;在接收端,UDP从下层接收数据,然后送达应用层。在该传输过程中,UDP之提供一个基本的差错检测服务,如果检测没有错误,就直接交给应用层;否则直接丢弃。

  下面我们来看一下TCP提供的可靠传输服务:

2、TCP

  源端口号/目的端口号:用于多路复用/分解来自或送到上层应用的数据。什么意思呢?处于应用层的进程可能有很多,每个进程都有可能通过传输层发送数据到因特网或者通过传输层从因特网中接收数据。那么当传输层从因特网中接收到数据应该发送给应用层中的哪个进程?或者如何知道从应用层收到的数据是属于应用层中的哪个服务??其实这些的实现都是通过端口号的标识的。应用层中的每个网络服务都对应着一个端口号,通过端口号来标识对应的服务。所以说端口号是将传输层绑定到应用层的粘合剂。

  

  序号和确认号:被用来实现可靠数据传输服务。

  接收窗口字段:指示接收方接收缓冲区剩余大小,用于流量控制。

  首部长度字段:TCP首部中有一个选项字段的存在,也就是说TCP首部的长度是可变的,所以需要指明首部的长度。

  选项字段:用于发送方与接收方协商最大报文段长度(MSS)时,或在高速网络环境下用作窗口调节因子时使用。还定义了一个时间戳选项。

  RST、SYN、FIN比特:用于连接的建立和拆除。

  PSH比特:当PSH比特被设置时,表明接收方应该立即将数据交给上层。

  URG比特和紧急数据指针:URG比特指示报文段里存在着被发送端的上层实体置为“紧急”的数据;紧急数据的最后一个字节由16bit的紧急数据指针字段指出。当紧急数据存在并给出紧急数据尾的时候,TCP必须立即通知接收端的上层实体。

  检验和字段:同UDP检验和,提供差错检测。

  TCP 如何保证数据传输的可靠性??

  (1) 在发送数据之前,进行三次握手,保证与接收端相互可靠通信。下面来讲一个三次握手的过程:

  初始状态客户端和服务器都为CLOSED状态,服务器打开listen监听客户连接进入LISTEN状态;然后客户端发送一个SYN包,序列号为j,此时客户端进入SYN_SENT状态;当服务器接收到SYN包时,服务器进入SYN_RECV状态,并且发送一个带SYN的ACK,确认号为j+1,序列号为k;当客户端收到这个带SYN的ACK时,客户端进入ESTABLISHED状态,对于客户端来说,已经确认可以与服务器通信了,所以客户端就可以发数据给服务器了,此时客户端发一个ACK(ACK中可以包含数据信息)到服务器,确认号为k+1;在服务器接收到ACK之前,三次握手还没有完成,虽然客户端可以发数据给服务器,但是只能包含在ACK中,而服务器并不能发数据到客户端,只有当收到ACK后,服务器端进入状态ESTABLISHED状态。自此,三次握手完成,客户端可以与服务器端已经建立了连接,可以互相发送数据。

  一定要进行三次握手么,不能只进行两次或者四次??

  其实这个问题的本质是因特网中信道不可靠, 但是要在这个不可靠的信道上可靠地传输数据,三次握手是最小的理论值。

  如果只进行两次握手,那么当客户端发送一个SYN分组后,会发生两种情况:

  情况一:服务器接收到了这个SYN并返回ACK,无论客户端是否接收到了ACK,服务器都认为已经与客户端建立连接了,于是就开始向客户端发送数据。但是如果客户段没有收到ACK,那么客户端会认为与服务器没有建立连接,就不会接收服务器发来的数据,,也就是说直接丢弃服务器发来的数据,服务器发出的消息超时了,就重复发送数据,这就产生了死锁。

  情况二:客户端发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达服务器。本来这是一个早已失效的报文段。但服务器收到此失效的连接请求报文段后,就误认为是客户端再次发出的一个新的连接请求。于是就向客户端发送ACK,但是此时客户端没有发出请求,所以并不会理睬这个ACK,而服务器又开始发数据给客户端了,这时候,客户端又把这些数据都丢弃了,而服务器发出的消息超时了,就重复发送数据,也产生了死锁。

  (2) 通过确认和重传机制来保证数据的完整性和按序交付

  TCP把数据看成是无结构和有序的字节流,所以上面所说的报文段的序列号是该报文段首字节的字节流编号,而报文段中的确认号是主机期望从客户端收到的下一个字节的序号。我们来举个例子:

与其临渊羡鱼,不如退而结网。

深入理解TCP协议

相关文章:

你感兴趣的文章:

标签云: