我是靠谱客的博主 糟糕乌冬面,最近开发中收集的这篇文章主要介绍可靠的传输层协议——TCP协议,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

TCP协议

TCP协议工作在传输层,虽然它与UDP的下一层都是IP但是它却和UDP的效果完全不同,它是一种可靠的传输层协议

一、TCP协议封装


wkiol1c7bspap9k2aacmzr1euhu179.png

TCP数据段头部共有20个字节,包括16位的源端口号,16位的目的端口号,端口号与前面各层中的协议类型相似,都指的是上层将要交给谁,这个端口号就是主机上一个进程所绑定的一个入口,所以通过端口号和IP就能找到唯一主机的唯一进程。

32位序号:用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。序号是32 bit的无符号数,序号到达2^32-1后又从0开始

32位的确认序号:既然有序号标识,那就一定需要确认序号来确认收到了多少的字节数,所以确认序号就是在序号的数字上加尚某一个数。

4位的首部长度:TCP数据段的首部长度,它占了4个字节表明最多有60字节的段头。

16位的窗口大小:IP的流量控制由链接的每一个端口的窗口大小声明来控制,16位则最大的窗口为65535。

16位校验和:这是一个强制性的字段,由发端计算和存储,并由收端进行验证。

16位的紧急指针:有时候我们在发出去一个数据段后,程序中突然更改了数据,于是可以发送紧急数据报,这个指针会找到这个数据段

选项:字段可有可无,大多数情况下会设置MSS字段,表明最大能接受的报文段。

URG 紧急指针有效。

ACK 确认序号有效

PSH 接收方应该尽快将这个报文段交给应用层。

RST 重建连接。

SYN 同步序号用来发起一个连接。这个标志和下一个标志。

FIN 发端完成发送任务。


二、TCP三次握手、四次挥手与数据传输过程

TCP是面向连接的,在网络中两个互相看不到的主机之间建立可靠的链接是十分困难的事情,TCP使用三次握手进行连接。

链接中通常会使用

Sequence number(顺序号码)

Acknowledge number(确认号码)

还需要一些状态信息来描述通信双方的状态信息

LISTEN - 侦听来自远方TCP端口的连接请求; 

SYN-SENT -在发送连接请求后等待匹配的连接请求; 

SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认; 

ESTABLISHED- 代表一个打开的连接,数据可以传送给用户; 

FIN_WAIT_1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;

FIN_WAIT_2 - 从远程TCP等待连接中断请求; 

CLOSE-WAIT - 等待从本地用户发来的连接中断请求; 

CLOSING -等待远程TCP对连接中断的确认; 

LAST_ACK - 等待原来发向远程TCP的连接中断请求的确认; 

TIME_WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认; 

CLOSED - 没有任何连接状态;

wkiom1c7eyvsjbtdaae10hgcuv0104.png


上图说明了TCP建立连接和终止链接的三次握手和4次挥手的过程


三次握手过程:(我们假设左边是客户端右边是服务端)

1、开始时客户端和服务端都是CLOSED状态,客户端向服务器发起连接请求,发送SYN段

和一个Sequence number(顺序号码)最开始的序号一般是一个1~2^32的随机数,括号里

面表示发送的数据大小,第一次为0,mss字段是选项字段,声明自己可以接受的最大数据段

的字节数,自己的状态设置为SYN_SENT。

2、服务器为LISTEN状态,然后他收到了一个SYN字段的连接请求,它会向客户端发送一个

SYN和自己的Sequence number(顺序号码)这个号码最开始也是随机的,ACK确认段和一

个Acknowledge number(确认号码),因为客户端发送过来的SYN字段(那八位)也会占用

一个字节,所以确认号码是客户端序号+1,并且声明自己的mss大小,自己的状态设置为

SYN_RCVD。

3、客户端收到来自服务器的响应会发送一个ACK确认字段和确认号码,确认号码为服务器顺

序号码+一个字节,自己的状态设置为ESTABLISHED。服务器收到客户端响应后自己也置

ESTABLISHED状态。


四次挥手过程:

1、客户端关闭链接,要发送一个FIN字段和顺序号码以及ACK的确认号码要求关闭通道。

并将自己的状态设置为_FIN_WAIT_1状态。

2、服务器接收到FIN会先发送ACK确认自己已经收到该请求,并将状态设置为CLOSE_WAI

T状态,客户端收到确认信息后将自己状态改为_FIN_WAIT_2,继续等待服务器。

3、服务器发送FIN关闭连接,和ACK与确认顺序号,并将自己的状态置为LAST_ACK。

4、客户端收到服务器的决定后将自己置为TIME_WAIT状态,并发送ACK和确认号码。服务

器接受后关闭。


在四次挥手的过程中客户端和服务器也会关闭自己的相应读写通道:

1、客户端关闭自己的读通道。

2、服务器端关闭自己的写通道。

3、客户端关闭自己的读通道。

4、服务器端关闭自己的写通道。



TIME_WAIT和CLOSE_WAIT


一、CLOSED_WAIT状态

发起TCP连接关闭的一方称为client,被动关闭的一方称为server。被动关闭的server收到FIN

后,但未发出ACK的TCP状态是CLOSE_WAIT。出现这种状况一般都是由于server端代码的

问题,如果你的服务器上出现大量CLOSE_WAIT,应该要考虑检查代码



二、tmie_wait状态:

根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方 socket将进入

TIME_WAIT状态。TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),在

Windows下默认为4分钟,即240秒。

它的设计为了两方面的需求


1>保证TCP的全双工能够有效的关闭。

如果client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server

没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由Client

已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不ACK,

Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却

导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保

TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。


2>保证这次链接的重复数据段有效的消失。

如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与

刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般

来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号

是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后

才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依

据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的

新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以

保证本次连接的所有数据都从网络中消失。



总结:还有很多细节没有熟悉,还有很多知识没有学到,协议的设计

真的很全面。

转载于:https://blog.51cto.com/wpfbcr/1774505

最后

以上就是糟糕乌冬面为你收集整理的可靠的传输层协议——TCP协议的全部内容,希望文章能够帮你解决可靠的传输层协议——TCP协议所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部