网络原理(TCP协议—协议格式,性质(上),状态)
目录
1.TCP协议段格式。
2.TCP协议传输时候的性质。
2.1确认应答。
2.2超时重传。
2.3连接管理。
2.3.1 三次握手。
2.3.2四次挥手。
3.TCP常见的状态。
1.TCP协议段格式。
TCP协议段是由首部和数据两部分构成的。首部包含了TCP通信所需要的各种控制信息,而数据部分则是实际要传输的应用层数据。
下面小编通过图片给大家进行描述:
下面解释下上述协议段里面各部分的含义(下述所说的长度都是以比特为单位):
1.源端口号:16位。用于标识发送方应用程序使用的端口号。2.目的端口号:16位。用于标识接收方应用程序使用的端口号。
3.序列号:32位。对字节流进行编号,用于保证数据的有序传输和检测数据丢失。第一个自己的序列号由发送方随机生成。
4.确认序列号:32位。接收方期望收到发送方下一个报文段的第一个数据字节的序列号。用于确认数据是否传输成功。
5.数据偏移:4位。表示该TCP头部有多少个32位bit(4字节为单位)
6.保留位:6位。当前先保留着,防止后面要使用。
7.控制位:6位。
URG:紧急指针有效标志。
ACK:确认号是否有效。
PSH:提示接收方应尽快将数据交付给应用层。
RST:重置连接标志。
SYN:同步序列号标志,用于建立连接,我们把携带SYN标识的称为同步报⽂段。
FIN:结束标志,用于关闭连接,我们称携带FIN标识的为结束报⽂段。
8.窗口大小:16位。表示发送方的接受窗口大小,用于流量控制。
9.校验和:16位。对传输的数据进行传输前后计算并进行对比,确保数据传输的完整性。
10.紧急指针:16位。当URG标志置为1时有效,指出紧急数据的末尾在报文段中的位置。
11.选项:可变。提供额外的功能,如:最大报文段长度,窗口扩大因子等。
2.TCP协议传输时候的性质。
2.1确认应答。
我们观察下面的图:
我们每次从一个主机上面传输信息传给另外一个主机的时候,我们会先传输一次,之后接收方会给发送方返回自己收到了,并且下一次传输从哪里开始。
2.2超时重传。
我们观察下面的图片:
图1:
我们观察图一,发现我们丢包的现象是在传输数据的时候丢失的,我们的TCP对等待一定自己设置的时间,要是发送方还是没有接受到接受方所返回的确认应答操作,就会让主机1再次发送信息,重新进行操作。
但是我们观察上述的流程,我们会发现还有一种可能,是应为确认应答没有返回回来。
图2:
上述图片展示的就是我们的第二种可能,是在接受方传输确认应答的时候,出现了问题。
我们会发现主机2会接收到重复的信息,TCP协议就会给我们识别出来重复的信息,之后将重复的丢弃掉。我们就通过我们前面所提到的序列号进行解决,很容易就达到去重的效果。
那么还有一个问题值得我们考虑,就是我们中间等待的时间?
我们等待的时间就是我们 单趟路程*2 的总时间,但是在实际情况中,TCP为了保证无论在任何环境下都能比较⾼性能的通信, 因此会动态计算这个最⼤超时时间。
2.3连接管理。
在连接管理的阶段,TCP会进行三次握手建立连接和四次挥手断开连接,我们的的连接管理是虚拟的,只保存双方关键的信息。
2.3.1 三次握手。
下面我先通过TCP在代码中的运行过程给大家说明下:
我们观察上述的图片,我们可以轻易的看到客户端给服务器先发送了一次信息,之后服务器给客户端发送了两次信息,最后客户端给服务器再次发送了一条信息。
可能会有同学提出疑问,上述图片中我们明明传输了四次,为什么说的是三次握手?
之所以我们说的是三次握手,是因为我们中间的两次服务器给客户端发消息的过程,可以合并为一处,之所以可以合并为一处是因为SYN和ACK是内核控制的,和代码没有没有关系,所以可以合并。
这里呢我们进行的三次握手,是是能由客户端发起的。
握手的意义:
1.验证链路是否畅通。
2.发送和接受能力是否正常。
3.让通信双方协商关键信息。
我们所进行的握手和生活中是一样的。例子:当我们长时间不回家的话,我们过年回家的时候就会很大可能碰到我们的老朋友,我们见面了指定会进行一下寒暄的,当然了我们也是会进行握手的,我们进行握手就好比我们进行了双方信息的确认。还有就是为啥要进行验证链路是否正常,因为我们只有正常的话才会可能进行信息的正确传递。例子:相比大家都做过地铁,我们每天早上进行的第一趟地铁运行的话,都会进行一趟空车的跑动,就是为了防止后面要是在载着一车的顾客的情况下出现问题,我们跑一趟之后就知道是否可以正常运行,这样我们后面就可以进行及时的修改。
2.3.2四次挥手。
我们进行挥手的最终目的就是为了释放没有再运行的空间。
图片:
我们观察上图,大家可能观察到和之前的三次握手好像没有什么区别,无非就是将每次进行的控制位进行了更改,那这为什么就成了四次挥手了呢!
大家观察前面的三次握手,是因为中间的两次是可以进行合并的,那这叫做四次挥手,就是中间的两次不会每次都能进行合并。我们要想够清楚为什么是不一定能够进行合并的原因是什么?那是因为我们最后在进行挥手的时候进行的是Fin,这个主要是由我们在程序里面的代码进行控制的——close() ,当我们在主程序执行完了之后再finally里面,close()前面有大片的代码需要进行执行的时候,就会记性长时间的等待,所以中间两次的ACK(确认信息)首先进行返回,最后后面的Fin在记性返回,这就将中间的两次进行了分离。
前面我们说了我们为什么不能进行合并的原因,那么我们要是能进行合并的时候,办法也是非常显而易见的,就是Fin触发close()之间的时间是本身不长的并且ACK可以往后面拖一段时间,这样我们就可以将中间的两次进行合并,这就是我们的四次挥手。
3.TCP常见的状态。
1.CLOSE:默认状态。这是TCP连接的最初和最终的状态,意味着没有任何连接的存在。在JAVA里,当SOCKET对象还没有进行创建的时候,或者连接关闭的时候,就处于该状态。
2.LISTEN:随时可以进行连接。
3.ESTABLISHED:客户端和服务器的连接已经建立好。客户端收到服务器的SYN+ACK报文后,发送ACK报文,之后客户端和服务端都进入ESTABLISHED 状态,此时TCP连接成功建立,双方可以进行数据传输。在JAVA里面,当SOCKET连接成功后,就处于该状态。
4.CLOSE_WAIT:被动断开连接的一方的状态。接受Fin 报文的乙方接收到 Fin 报文后,发送 ACK 报文,然后进入 CLOSE_WAIT 状态。此时是关闭等待状态,需要调用close() 方法进行关闭连接,发送FIN 报文。
5.TIME_WAIT:等待连接彻底释放。发送 FIN 报文的一方收到对方的 ACK 报文后,进入 TIME_WAIT 状态,等待一段时间后,才会进入 CLOSED 状态。中间的等待时间是为了最后一个ACK 报文能够到达到达对方。