当前位置:首页 » 《随便一记》 » 正文

TCP协议_小白猿同学

5 人参与  2021年12月26日 13:42  分类 : 《随便一记》  评论

点击全文阅读


TCP

​ 之前我们已经提到过TCP/IP五层模型,TCP协议属于传输层协议,其是以太网协议和 IP 协议的上层协议,也是应用层协议的下层协议。同时,我们简单的知道,数据从应用层发下来,会在每一层都会加上头部信息,进行封装,然后再发送到数据接收端。这次,我将详细给大家讲解一下TCP的报文数据格式

1. TCP字段

首先,我们先来看一下 TCP 的报文格式

TCP字段

下面分别对其中的字段进行介绍

1.1 端口号

  • 源端口:源端口和IP地址的作用是标识报文的返回地址。
  • 目的端口:指明接收方计算机上的应用程序接口。

其各占2个字节,这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接。

1.2 序号(seq)

​ 占4个字节,是本报文段所发送的数据项目组第一个字节的序号。在TCP传送的数据流中,每一个字节都有一个序号。例如,一报文段的序号为500,而且数据共500字节,则下一个报文段的序号就是1000(500+500=1000),其确保了TCP传输的有序性。之后将讲到其作用

1.3 确认序号(ack)

​ 占4字节,是期望收到对方下次发送的数据的第一个字节的序号,也就是期望收到的下一个报文段的首部中的序号;确认序号应该是上次已成功收到数据字节序号+1。只有ACK标志为1时,确认序号才有效。

1.4 数据偏移

​ 占4比特,表示数据开始的地方离TCP段的起始处有多远。实际上就是TCP段首部的长度。由于首部长度不固定,因此数据偏移字段是必要的。数据偏移以32位为长度单位,也就是4个字节,因此TCP首部的最大长度是60个字节。即偏移最大为15个长度单位=1532位=154字节。

1.5 保留

6比特,供以后应用,现在置为0。

1.6 6个标志位

名称作用
URG紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针。
ACK确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
PSHpush标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
RST重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
SYN同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。
FINfinish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。

1.7 校验和

​ 奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。

1.8 窗口大小

这个将在下一节结合滑动窗口重点介绍!!!

其余部分暂不介绍

在网络中,我们发送数据需要考虑到以下问题:

  • 我们发送的数据对方是否能收到?
  • 如果收到,收到的数据有没有发送错误?
  • 如果发送多条数据,对方接收的顺序是否按照发送的顺序?
  • 如果接收方收到了多条重复数据,是否能丢掉重复数据?

接下来,将给大家讲解TCP协议如何解决这些问题

2. 重点分析

2.1 序号和确认序号

假设现在A同学想去B同学家里玩游戏,于是他给B同学发消息,如果消息没有出现错误且顺序正确,结果如下所示

image-20210809145839543

但是,由于数据的长度不同或者传输网络不同,先发送的数据不一定先到达,也就是说,接收方接收到的数据可能是乱序的,所以可能出现下面这种情况

image-20210809150743283

​ 如果消息正确且顺序正确,那么A同学就能找B同学玩游戏了,但是如果出现了第二种情况,那么A同学就不能找B同学玩游戏了。为了避免出现这种问题,在TCP中就引入了序号、确认序号的字段,如下所示,A同学的消息标注了序号,B同学在回复时消息时,将带上其回复的是A同学哪序号对应的消息,这就保证了消息的传输的准确性。

image-20210809151548138

但是,真正的序号和确认序号不是这么简单

序号(seq)

  • 初始序号是随机的,为了防止网络攻击
  • 如果发送多个数据,每个数据都会带着一个序号

确认序号(ack)

  • 接收方收到数据后,是知道数据所带着的序号的,根据序号给出确认序号(告诉发送方下次给我发的序号),发送给发送方,发送方就知道接收方收到了哪些数据

真正的传输,如下所示,(初始序号125为随机值)

image-20210809152613085image-20210809154204690

2.2 确认应答和超时重传

同样,假设现在A同学想去B同学家里玩游戏,于是他给B同学发消息,你在家吗?但是A同学没有收到回复的消息,那么B同学可能会有以下几种情况

  • B同学不想回A同学消息
  • B同学没收到消息
  • B同学回复了消息A同学没收到

如果B同学回复了,且回复了A同学,那么这就是类似于确认应答机制,当主机B收到主机A发送的数据后,会给主机A回一个ACK,表示我收到了你的数据,并且向主机A发送ASN,告诉主机A我希望你下次发送的序号。

对于上述的后两种情况,由于不知道B同学是否收到消息,所以A同学在等待十分钟后,再次给B同学发了条同样的消息,这就类似于超时重传

如果是第一种情况,B同学将删除A同学发送的消息的其中一个,只保留一份,这就类似于TCP协议丢掉重复发送的数据。

2.3 建立连接-三次握手

​ 为了保证连接的正常,TCP采用“三次”握手机制。举个类似的例子,这次以A同学给B同学打电话为例,想要确保双方都能听到对方的话,刚开始需要以下过程

image-20210809154900761
  • 第一次握手:刚开始,由于A同学不知道自己和B同学 手机的听筒和麦克风是否正常,所以A同学说“你能听到吗?”
  • 第二次握手:B同学听到后,说明A同学的麦克风和B同学的听筒正常,但是B同学不知道A同学的听筒和自己的麦克风是否正常,所以为了确认,B同学说:“我能听到,你能听到吗?”。这里的**“我能听到”**,同时也向A同学表示A同学的麦克风和B同学的听筒正常。
  • 第三次握手:A同学收到B同学的消息后,就证明了A同学听筒正常,B同学麦克风正常

以上三次握手就保证了A、B同学的听筒和麦克风都正常,这就保证了通话的正常~这就类似于网络建立连接时的三次握手

接下来,我们详细介绍一下网络中的三次握手

**第一次握手:**客户端TCP进程也先建立传输控制块TCB,然后向服务端发送连接请求报文段,此时SYN=1,随机选定一个初始序号seq=x,,此报文不能携带数据,但是要消耗掉一个序号,发送完毕后,客户端进入SYN-SENT(同步已发送)状态

**第二次握手:**服务端收到客户端请求连接报文段后,若同意建立连接,则发送确认报文,确认报文中SYN=1、ACK=1,确认号ack=x+1,同时随机选定一个自己序号seq=y,确认报文段同样不能携带数据,但是也要消耗掉一个序号,发送完毕后服务端进入SYN-RCVD(同步收到)状态

**第三次握手:**客户端收到确认报文后,检查ACK=1,ack=x+1是否正确,若正确,则向服务端发送确认报文,确认报文中ACK=1,ack=y+1,seq=x+1,发送后进入ESTAB-LISHED状态,服务端收到确认报文后,也进入ESTAB-LISHED状态,此时双方TCP连接正式建立。

在打电话例子中的“我能听到,你能听得到吗?”中,“我能听到”相当于ACK, “你能听得到吗”相当于SYN

当服务器端调用 new ServerSocket后,就会绑定端号,并进入LISTEN状态

当客户端调用 new Socket后,进入SYN-SENT状态,就会尝试和服务器建立连接并触发三次握手。

上面的连接建立过程就是TCP三次握手,具体过程如下,(此图来自公众号《程序IT圈》)

tcp

两次握手可以吗?

不可以,如果没有第三次,服务器端将不知道客户端能不能收到自己的消息。

如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

2.4 断开连接-四次挥手

为了更好的理解,我们再次使用打电话的例子来解释一下,如下图所示

image-20210809165112138

看了这个图,大家可能会有疑问,为什么要把 好的 再见 这两个分开呢?

当 服务器收到FIN(即我们明天再聊),系统内核将立刻发回一个ACK**(好的)这时B的接受缓冲区中可能还有没有处理完的任务,必须等B将其处理完毕后才能关闭客户端连接,发送一个FIN(再见)**给客户端。

具体流程:

数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

  • TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。此时,客户端进入FIN-WAIT-1(终止等待1)状态
  • 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。此时,服务端就进入了CLOSE-WAIT(关闭等待)状态,客户端收到ACK后,就进入FIN-WAIT-2(终止等待2)状态。
  • 服务器关闭客户端的连接,发送一个FIN给客户端。此时,服务器就进入了LAST-ACK(最后确认)状态。
  • 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态

为什么TIME-WAIT状态要等待2MSL呢?

​ 由于当客户端给服务器端发送ACK可能出现丢包情况,这时服务器端会没收到客户端的ACK,将会消息重传FIN,如果此时客户端关闭连接,将导致服务器端无法关闭,所以等待2MSL,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

图片

三次挥手行不?

通常情况下不行,因为FIN 和ACK的触发时机不同。但如果触发了延时应答机制,可以三次。

致服务器端无法关闭,所以等待2MSL,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

图片

三次挥手行不?

通常情况下不行,因为FIN 和ACK的触发时机不同。但如果触发了延时应答机制,可以三次。


点击全文阅读


本文链接:http://zhangshiyu.com/post/32164.html

报文  序号  同学  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1