【网络自定向下学习】——TCP报文段的详细解析

  • 个人主页:努力学习的少年
  • 版权: 本文由【努力学习的少年】原创、在CSDN首发、需要转载请联系博主
  • 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦

目录

一. Tcp报文段的结构

二. 首部长度

三. 窗口大小

四. 序列号和确认序号

1.序列号

2.确认序号

3.序号和确认序号的一个学习案例 

 五. 6比特标志位

1. 标志位的含义

2.建立通信的过程

3.断开连接

六. 写到最后


一. Tcp报文段的结构

Tcp报文段是由报头字段数据字段组成,数据段包含一块应用数据

【网络自定向下学习】——TCP报文段的详细解析_第1张图片

 

源端口号:表示发数据那个进程的端口号。

目的端口号:表示收数据那个进程的端口号。

校验和 :写入取人数据是否完整的数值

选项:扩展Tcp功能时使用,决定了Tcp报头的大小

紧急指针:当标志位URG为1时,则紧急指针生效,当紧急数据存在并给出指向紧急数据尾的指针时,TCP必须通知接受方的上层实体。

二. 首部长度

      在Tcp报头字段中的选项可有可无,如果Tcp报头中没有选项的话,那么Tcp报头字段的大小为20个字节,但是如果Tcp报头字段中加入选项后,那么Tcp报头字段的大小就不止20个字节,所以Tcp的报头字段的大小是不固定的。为了标识Tcp报头的大小,Tcp就引入首部长度的概念。首部长度的大小是4个bit位,它最大时是1111,也就是15,但是首部长度的基本单位是4个字节,也就是说报头的最大的大小是15*4,也就是60个字节。

  1. 首部长度是标识Tcp报头的大小
  2. 首部长度的基本单位是4个字节
  3. 报头字段最大是60个字节,首部长度存放的是1111.
  4. 报头字段最小是20个字节,首部长度存放的是0101,也就是没有加入选项。

问题:Tcp中的报头和有效载荷是如何分离的?

    当两台主机建立通信的时候,会每次发送报文段(报头+有效载荷)的大小,所以当一台主机收到一个报文段的时候,Tcp层面会根据报头字段中的首部大小确认报头的大小,然后读取根据这个大小读取出报头,剩下的就是有效载荷。

三. 窗口大小

     Tcp通信过程是会建立发送缓冲区和接受缓冲区的,当主机A和主机B建立好Tcp通信的时候,主机A和主机B都会在Tcp协议层面建立好发送缓冲区和接受缓冲区。发送缓冲区是将数据发送给对端主机的接收缓冲区上的。

【网络自定向下学习】——TCP报文段的详细解析_第2张图片

    窗口大小是用来进行流量控制的,它用来告诉对端主机自己的接收缓冲区剩余的大小。当两台主机建立通信的时候,通过三次握手互相交换各自窗口的大小,就能够互相知道对方主机的接收缓冲区的大小。同时,给对端发送报文字段的时候,也可以告诉对端主机自己的接收缓冲区接收缓冲区剩余的大小。

    举个例子:当主机B中的接收缓冲区只剩下1000字节大小的时候,那么主机B会将回应过去的Tcp协议中的窗口大小是1000,当主机A收到主机B的响应后,通过响应的窗口大小判断出主机B的接收缓冲区剩余的大小,因此下一次主机A给主机B发送数据的时候是不会超过1000个字节的数据,这样就可以防止主机B接收缓冲区满了之后出现丢包的情况。

四. 序列号和确认序号

1.序列号

    在我们的发送缓冲区中的每一个字节的数据都有一个编号,这个编号就是我们的序列号

    Tcp把数据看成一个无结构但是有序的字节流,我们从TCP对序号的使用可以看出这一点,这是因为序号建立再传送的字节流上,而不是建立再传送的报文段的序列之上。一个报文段的序号是该报文段首字节的字节流的编号。假设一个报文段的大小是1000个字节(报文段大小在建立同时新的时候双方就已经约定好了大小), 则第一报文段的大小是1,第二个报文段的大小是1001,第三个报文段是2001,以此类推。每一个序列号被填入到相应TCP报文段报头的序列号字段中。

【网络自定向下学习】——TCP报文段的详细解析_第3张图片

 

当接收方收到数据的时候,会根据序列号,按照顺序排列成一段,因此序列号可以解决数据在网络发送的过程中出现乱序的问题。

2.确认序号

    TCP是全双工的,因此主机A在向主机B发送数据的同时,也会接收来自主机B的数据。从主机B到达的每个报文段中都有一个序列号用于从B流向A的数据。主机A填充进报文段的确认序号是主机A期望从主机B中收到下一个字节的序列号举个例子

    假设主机A收到主机B的1~1000的所有字节,同时假设它要发送一个报文段给主机B,主机A等待主机B中1001即其以后的字节,那么主机A会在报文段的确认序号字段填充上1001.

再举一个例子: 

     假设A收到一个来自主机B的包含字节1~1000的报文段,以及另一个包含字节2001~3000的报文段。由于某种原因,主机A没有收到主机B发出来的包含字节1001~2000的报文段,主机A为了重组主机B的数据流,仍在等待字节1001(和其后的字节),因此,A发送给B的下一个报文段中将在确认序号中填充1001

      在第二个例子中,有个微秒的问题,当主机在收到第二个报文段(字节1001~2000)之前收到第三个报文段(字节2001~3000).因此,第三个报文失序到达,问题是:当主机在TCP连接的时候收到的失序报文段该怎么办?有趣的是,TCP并没有明确规定任何规则,而是把这个问题留给实现TCP编程人员去处理,他们有两个基本选择.

  • 1.接收方立刻丢弃失序的报文段
  • 2.接收方保留失序的报文段,并等待缺少字节以填充该间隔。

显然,后一种选择对网络带宽更加有效,也是实践中采用的方法。

3.序号和确认序号的一个学习案例 

    假设主机A与主机B建立好了TCP连接,然后主机A与主机B开始通信,假设主机A和主机B的起始序列号分别是11和45.假设每一个报文段为1.

(ps:Seq为序列号,ACK为确认序号)

        【网络自定向下学习】——TCP报文段的详细解析_第4张图片

 如上图所示,第一个报文段是主机A发送给主机B的,其数据段中包含字符"A"的ASCII码,其序号字段是11,这如我们刚讲到的那样。另外,由于客户机还没有接收到来自服务器的任何数据,因此该报文段中的确认序号中填充的是45。

第二个字段是由主机B发送给主机A,它有两个目的:第一个目的是为主机B所收到的数据提供确认,因此主机B在确认序号中填充12,告诉主机A,它已经收到字节11及以前的所有字节,现在正等着字节12的出现。第二个目的是发送字符"B”,因此,在第二个报文段中的数据段填充的私字符" B " 的ASCII码值,并且将报文段的序列号填充为45。注意到对客户机到服务器的数据的确认被装载在一个程种主机B到主机A的数据的报文段中,这种确认被称之为捎带在主机B到主机A的数据报文段中。

第三个报文段是主机A发送给主机B的,它唯一的目的是确认已从主机B中收到数据。该报文段中的数据字段为空,该报文段中的确认序号填充为46,因为主机A收到了主机B字节流为12及以前的字节,它现在在等字节80的出现。即使没有报文段中没有数据,但报文段中一定需要填充某些序号。

 五. 6比特标志位

1. 标志位的含义

【网络自定向下学习】——TCP报文段的详细解析_第5张图片

  • ACK:如果ACK为1是用于指示确认字段中的值是有效的,即该报文段包括一个对已被接收报文段的确认
  • URG:如果URG为0,紧急指针无效,无需关注紧急指针,如果URG为1,那么紧急指针就有效.
  • SYN:该比特位是请求对端开始建立连接。
  • FIN:该比特位是要求与对端断开连接。
  • PSH:该比特位设置时,指示对端立即将数据交给上层。
  • RST:当一直没有收到对端的确认时,则会强制切断通信,然后重新建立通信。

2.建立通信的过程

两台主机开始建立通信的时候需要ACK和SYN来联系。下一篇文章将会详细地讨论TCP连接的建立过程。主机A与主机B连接建立的过程中:

【网络自定向下学习】——TCP报文段的详细解析_第6张图片

  1.  第一个报文段是主机A给主机B发送一个SYN设置为1的报文段,表示向主机A向主机B发起连接请求。
  2. 第二个报文段是主机B给主机A的,该报文段将SYN和ACK都设置为1,它有两个目的:一个表示主机B收到主机A的报文段,另一个表示主机B向主机A发起连接请求。
  3. 第三个报文段是主机A给主机B的,该报文段将ACK都设置为1,表示的是主机A确认收到主机B连接请求。

       前两个报文段不承载" 有效载荷 ”,也就是不包含应用层数据,而第三个报文可以承载有效载荷,由于在这两台主机之间发送了3个报文段,所以这种连接建立过程常被称之为三次握手。建立过程中会确认好接下来双方发送的报文段的大小。比如确认好的报文段为1000个字节,那么接下来双方每次发送的报文段都为1000个字节。

TCP不能保证百分之百连接的,因为:

    在上面的连接过程中,如果第一个报文段丢失后,在一段时间内主机A没有收到第二个报文段,那么主机A就认为第一个报文丢失了,就会重发第一个报文段,直到主机A收到第二个报文为止。同样,如果第二个报文段丢失后,在一段时间内主机B没有收到第三个报头进行确认,那么主机B就会重发第二个报文段,直到主机B收到第三个报文为止。但是如果第三个报文段丢失后,主机A和主机B不知道,因为第三个报头没有响应报文段,如果主机B没有收到第三个报文段,则主机B是不会建立连接的,也就是说它没有建立好通信缓冲区(发送缓冲区+接收缓冲区)。但是主机A发送完第三个报文后会认为已经跟主机B建立好连接,就会建立好通信缓冲区。此时如果主机A再给主机B发送报文段的时候,当主机B收到报文段的时候,就知道对端已经建立好连接,但是自己没有建立好连接,就会发送一个RST为1的报文段给主机A,告诉它自己没有建立好连接,请断开连接,再重新建立连接。

【网络自定向下学习】——TCP报文段的详细解析_第7张图片

3.断开连接

TCP断开连接的过程需要用FIN和ACK来联系的,具体断开细节下篇文章会将会讨论。

【网络自定向下学习】——TCP报文段的详细解析_第8张图片

六. 写到最后

      到此为止TCP报文段就讲解完了,同时也欢迎大家在评论区上同博主进行交流,如果有什么问题,我也可以给大家提供支持。

   最后,如果觉得文章对你有帮助的话,请给博主关注,点赞,收藏,博主将会不断做出优质的文章给大家。

系列文章

  1. 【Linux网络(C++)】——网络套接字(TCP/UDP编程模型)多进程,多线程,线程池服务器开发(画图解析)
  2. 【linux多线程(四)】——线程池的详细解析(含代码)

    3.【项目】----自主搭建个人博客

你可能感兴趣的:(linux网络,c++,开发语言,后端,tcp/ip,leetcode)