TCP协议详解!!!

TCP和UDP是TCP/IP中传输层中两个最具代表性的协议,TCP提供可靠的通信传输,UDP则是常被应用于广播和细节控制(相比而言,不太可靠)


可是,TCP的可靠性表现在哪里??它的报文格式又是咋样的呢??


TCP(虽然是面向字节流的,但TCP传送的数据单元却是报文段)

1.   是面向字节流,TCP中的“流”(stream)指的是流入到进程或从进程流出的字节序列。“面向字节流的含义是”:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。TCP不保证接受方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系(例如:发送方应用程序交给发送方的TCP共10个数据块,但是接受方的TCP可能只用了5个数据块就把收到的字节流交付给了上层应用程序)。但是:接受方应用程序收到的字节流和发送方应用程序发出的字节流完全一样。接受方的应用程序必须有能力识别接受到的字节流,然后把它还原成有意义的应用层数据

2.   面向连接,也就是说tcp在传输之前,首先有一个建立连接的过程

3.   tcp的可靠性传输,也就是说它能在逻辑上保证传输是可靠的,顺序控制(不失序),重发机制(数据丢失),端到端校验和(传输错误),拥塞控制等功能

4.   缓冲传输,就是说TCP可能不会立即发送这个段,它可能会把这些段放入缓冲区,等到一定的时机然后再发送出去

5.   全双工,(TCP允许通信双方的应用进程在任何时候都能发送数据,TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据,在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事情了,而TCP在合适的时候把数据发送出去,在接受时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据),而半双工(只能发送或只能接收,例如收音机就是只能接收的)

6.   流量控制,通过窗口控制达到流量控制的目的



报文(message )  

    报文是网络中交换与传输的数据单元,也是网络传输的单位。报文包含了将要发送的完整的数据信息,其长短很不一致。报文在传输过程中会不断的封装成分组、包、帧来传输,封装的方式就是添加一些信息段,那些就是报文头。
分组:

就是TCP发送的保温的,tcp虽然是面向字节流的,但是TCP传送的数据单元却是报文段。

数据报(datagram)

    面向无连接(UDP)的数据传输,工作过程类似于报文交换。采用数据报方式传输时,被传输的分组称为数据报。
帧(Frame)
    Frame,数据链路层的协议数据单元(protocol dataunit)。数据链路层的主要职责是控制相邻系统之间的物理链路,它在传送“比特”信息的基础上,在相邻节点间保证可靠的数据通信。为了保证数据的可靠传输,把用户数据封装成帧。




TCP和UDP在发送报文时所采用的方式完全不同,TCP对应用进程一次把多长的报文发送到TCP的缓存中是不关心的。TCP根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应该包含多少个字节,如果应用进程传送到TCP缓存的数据块太长,TCP就可以把它划分短一些再传送,如果应用程序一次只发送来一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,没有检验机制,也是为了加快传输速度的情况,故udp本就不需要缓存机制,及时的将数据直接发送过去了.


TCP的连接:

TCP把连接作为最基本的抽象。每一条TCP连接有两个端口。那么,TCP连接的端口是什么呢??不是主机,不是主机的IP地址,不是应用进程,也不是运输层的协议端口。TCP连接的端点叫做套接字(socket)或者插口。根据RFC793的定义:端口号拼接到(contatenated with)IP地址即构成了套接字。因此:套接字的表示方法是在点分十进制的IP地址后面写上端口号,中间用冒号或者逗号隔开。例如:IP地址是:192.168.1.100,而端口号是80,那么得到的套接字就是(192.168.1.100:80)

套接字:socket = (IP地址:端口号)

每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。

虽然有时为了方便,我们也可以说,在一个应用进程和另一个应用进程之间建立了一条tcp连接,但一定要注意的是:TCP连接的端点是套接字,即(IP地址:端口号),也应注意的是:同一个IP地址可以有多个不同的Tcp连接,而同一个端口号也可以出现在多个不同的TCP连接中。


我们可以看到IP报文里面封装了很多的东西,有IP头部(占用20字节),TCP头部(占用20字节),接下来就是TCP数据了,同时,称TCP头部和TCP数据为IP的数据,这也就是不断封装的过程,同理当传过去之后,就有了解封的过程


TCP报文:


我们可以看到:TCP报文 = TCP头部  +  数据

TCP头部是20个字节:

1.    先是源端口号和目的端口号各占2个字节(结合IP头部的源IP地址,目的IP地址,就已经构成了简单地TCP连接)


2.    然后是序列号(这个报文段的第一个数据字节序号),确定号各占4个字节(仅当ACK为1时有效,表示期望收到  的下一个字节的序号,三次握手,四次挥手中会提到),序号范围是:0-2^32-1(4个字节,32位,即就     是:4294967296)个序号。序号增加到2^32-1后,下一个序号又回到0。也就是说:序号使用mod运算。TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。即本报文段所发送的数据的第一个字节的序号,例如:一报文段的序号字段值是301,而携带的数据共有100字节,这就说明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段(有的话)的数据序号应当从401开始,即下一个序号字段值应为401,这个字段也叫做:报文段序号。


3,确认号(4个字节):是期望收到对方下一个报文段的第一个数据字节的序号。例如:B正确收到了A发送过来的一个报文段,A的序号字段值是501,而数据长度是200字节(501-700),这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701


总之:若确认号 = N,则表明:到序号N-1为止的所有数据都已正确收到

3.    再就是头部长度(也称为:数据偏移),由于首部中还有长度不确定的选项字段,因此数据偏移是必要的,因为单位是32位字(即就是4字节),占4位(最大是15,也就是15*4 = 60个字节),接下来就是6位的保留,必须全部为0

4.    6个标志位

       URG为1是,紧急指针有效,告诉系统此报文段中有紧急数据,应当尽快传送(高优先级数据),而不要按原来的排队顺序来传送,例如:我们运行了一个程序,但是里面是死循环,程序一直都不退出,我们要让程序退出,键入中断命令(Control + C),如果不使用紧急数据,那么这两个字符将在接受TCP缓存的末尾,也就是只有等所有的数据都被处理完毕后这两个字符才被交付到接受方的应用进程,也就是说:我们的程序一直在死循环着,但:如果我们使用紧急指针,发送方就把紧急数据插入到本报文段数据的最前面,仅接着执行。window下的任务管理系统也是这个原理。


       ACK为1时, 确认号有效,当ACK = 0时,确认号无效,TCP规定:在连接建立后所有传送的报文段都必须把ACK置1

       PSH为1时, 当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送psh操作。这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接受方TCP收到PSH = 1的报文段,就尽快的交付给接收应用进程,而不再等待到整个缓存都填满了后再向上交付。

        RST为1时, 表示TCP连接中出现严重差错(由于主机崩溃或这其他原因),必须释放连接,然后在重新建立运输连接。RST置1还用来拒绝一个非法的报文段或拒绝打开一个连接。

        SYN为1时, 用来发起一个连接,在连接建立时用来同步序号。当SYN = 1而ACK = 0时,表明这是一个请求报文段。对方若同意建立连接,则应在响应的报文段中使用SYN = 1和ACK = 1。因此:SYN置为1就表示一个连接请求或连接接受报文。

        FIN为1时,   表示此报文段的发送方的数据已发送完毕。

5.    窗口尺寸(2字节),是[0, 2^16 - 1]之间的整数。窗口指的是发送本报文段的一方的接受窗口(并不是自己的发送窗口),窗口值告诉对方:从本报文段首部中的确认号算起,接受方目前允许发送的数据量。之所以要有这个限制,是因为接受方的数据缓存空间是有限的。接受方的数据缓存空间直接影响了发送发TCP报文段窗口数值的大小,如:设接受方发送的确认号是701,窗口字段是1000。这就说明:下一次,从701开始,发送方发送此报文段可以发送的范围是701-1700(1700最大,不一定发送这么多)

6.    检验和 占2字节。检验和字段检验的范围包括首部和数据这两部分。

7, 紧急指针,占2字节。紧急指针仅在URG = 1时才有意义,(紧急数据结束后就是普通数据),紧急指针指出了紧急数据的末尾在报文段中的位置。当所有紧急数据处理完后,TCP就告诉应用程序恢复到正常操作。值得注意的是:即使窗口为0时,也可以发送紧急数据。


8,选项:(长度可变,最长可达40字节,上图不太对!!!),当没有使用选项时,TCP的首部长度是20字节

      TCP最初只规定了一种选项,即就是最大报文段长度MSS(Maximum  Segment  Size)。MSS是每一个TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个TCP报文段。所以:TCP报文段长度减去TCP首部长度 = MSS,为什么要规定最大报文段长度MSS呢?并不是考虑接受缓存可能放不下TCP报文段中的数据,实际上,MSS与接受窗口值没有一点关系。我们知道:IP数据包 = IP首部 + TCP首部 + TCP报文段的数据部分,,,,若选择较小的MSS长度,网络的利用率就降低;设想在极端的情况下,当TCP报文段只含有1字节的数据时,在IP层各首部信息就要占用40字节,极低的网络利用率;但反过来,如果要使TCP报文段的数据非常长,那么在IP层传输时就要进行分片,在传到对面之后,就要把分片后的小的报文段装配成原来的TCP报文段,当传输出错时还要进行重传。

       因此:MSS应该尽可能大些,只要在传输层不需要进行分片就行。由于IP数据报所经历的路径是动态变化的,因此在要确定在当前路径上不需要分片的最大MSS,在连接建立的过程中(只要路径确定),双方都把自己确定能够支持的MSS写入这一字段,以后在不改变路径的情况下,就按这一数值进行传送,双方可以有不同的MSS值

       若主机未填写这一项,则MSS的默认值就是536字节长。因此在因特网的主机都能接受报文段长度是536 + 20(固定首部长度) =  556字节



tcp:应用数据被分割成TCP认为最合适发送的数据块,称之为段,发送给IP层

不可靠表现在以下几个方面:传输出错,丢包,重复(粘包), 失序,

出错:会通过网际校验和进行检验(如果数据在传输的过程中校验和丢失或出错,那么TCP将直接丢弃这个报文段,并且不产生确认(导致重传))

失序:报文头部会有一个序号,来保证传输的正常进行

重复:(基于字节流的传输,无边界,不能严格意义上的断开,说是一个字节一个字节的传,所以发送给目的端的时候,它接受的有时是不止一个流,可能一个,可能两个,我们不知道的,所以)也通过序号来保证不重复

丢包:超时重传机制  +  确认机制(一定时间内没有收到确认的消息就会启动重传,当TCP发出一个段之后,会启动一个定时器,等待目的端确认收到这个报文段,通常这个确认不是立即发送,而是推迟几分之一,如果源端不能收到确认,启动重传机制)


TCP发送的报文段是交给IP层传送的。TCP下面的网络所提供的是不可靠的传输,因此,TCP必须采用适当的措施才能使得两个运输层的通信变得可靠

理想的传输条件有以下两个特点:

1,传输信道不产生差错

2,不管发送方以多快的速度发送数据,接受方总是来得及处理收到的数据

也就是说:在这样的理想传输条件下,不需要采取任何措施就能够实现可靠传输

但是,实际的网络都不具备以上两个理想条件。但我们可以使用一些可靠传输协议,当出现差错时让发送方重传出现差错的数据,同时在接收方来不及处理收到的数据时,及时告诉发送方适当的降低发送数据的速度。


停止等待:

全双工通信的双方既是发送方也是接受方。我们此刻仅考虑A发送数据而B接受数据并发送确认,A叫做发送方,B叫做接受方。把传送的数据单元都成为分组,停止等待:就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组

1,无差错情况

      A发送分组M1,发完就暂停发送,等待B的确认。B收到了M1就向A发送确认。A在收到了对M1的确认后,就再发送下一个分组M2。同样的,A在收到了B对M2的确认后,再发送M3

2,出现差错

      B在接收M1时检测出了差错,就丢弃M1,其他什么也不做(不通知A收到有差错的分组,即就是B不向A发送分组确认),或者A发送的M1在传输的过程中就丢失了,这时B肯定什么都不知道。可靠传输协议是:A只要超过一段时间仍然没有收到确认,就简单的认为刚才发送的分组丢失了,因此要重传前面发送过的分组。这就是超时重传(就是说;A每发送完一个分组后,必须暂时保留已发送的分组的副本,同时设置一个超时计数器。如果在超时计数器时间到达之前,接收到了对方的确认,就撤销已设置的超时计数器和刚才分组的副本),还有一点:分组和确认分组都必须进行编号。这样才能确定到底是哪一个分组和对应的确认分组挂钩,,,此外:超时计数器设置的时间至少应该比数据在分组传输的平均往返时间更长一些。(如果太长,极大的降低了通信的效率,太短,将造成不必要的重传,浪费了网络资源,所以说;这个时间就不能太长或者太短,还取决于网络当时的拥塞情况,时间就不是一个定值)

3,确认丢失和确认迟到

      上面已经分析了A发送的分组M1在给B的过程中出了差错或者丢失了,这里我们来讨论其他的情况:B收到了A发送的正确的分组M1,但是B在发送M1的确认分组时:1,丢失了,2,由于网络拥塞等情况,导致确认分组延迟到达

       由于我们完全不知道是那种情况:所以我们一般会采用两种方式。

       1,没有接收到确认分组:达到了预先设置的超时计数器:A重新发送分组M1,B在收到了这个分组后,直接丢弃,不向上层交付。但是向A发送确认。不能认为已经发送过就不再发送,因为A之所以重传就是因为M1并没有收到对M1的确认

        2,由于网络拥塞原因等没有收到确认,导致B发送的分组确认延迟到达。A会收到重复的确认,处理就是:收下后就丢弃


信道利用率

停止等待协议对于可靠性还是很有用的,但就是信道利用率太低

假定A发送分组需要的时间是Td(就是将数据装入到tcp缓冲区的过程,等于分组长度/数据率)。在假如:分组正确到达B后,B处理分组的时间也可以忽略,但发送确认分组的需要的时间是Ta。如果A处理分组的时间也可以忽略不计,那么A在经过时间(Td + RTT + Ta)就可以发送下一个分组了,RTT是往返时间,

因为只是在时间Td内,才用来把程序或者数据的信息装载到tcp的缓存区中的,所以

信道利用率 = Td/(Td + RTT + Ta),其实某种意义上,经过的时间还应该再加上一个小的时间(相当于由于网络拥塞等浪费的时间)


当然为了改善传输效率,采用流水线传输,可连续发送多个分组,不必每发完一个分组就停顿下来等待对方确认,这可以使信道上一直有数据在传输,获取极高的利用率


连续ARQ协议

发送方连续发送多个分组,需要一个发送窗口(假设为5),把发送窗口向前滑动一个分组的位置。当发送方接受到了地一个分组的确认,于是把发送窗口向前移动一个分组的位置。

接受方一般都采用累计确认:接受方不必对收到的分组逐个发送确认,而是可以在收到几个分组后,对按序到达的最后一个分组发送确认,表示:到这个分组为止的所有分组都已经正确收到了

如果发送方发送了前5个分组,但是中间的第三个分组丢失了,这时接受方只能对前面两个分组发出确认。发送方无法知道剩余的三个分组去哪里了。而只好把后面的三个分组重新传一次。这就是Go-back-N(回退N),表示需要在退回来重传已发送的N个分组

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页