第二节:TCP/UDP/端口/三次握手/四次挥手/TCP滑动窗口机制

本文深入解析TCP和UDP这两种传输层协议的特点与应用场景,包括TCP的可靠传输机制、三次握手及四次挥手的过程,以及UDP的高效传输特性。此外,还探讨了长连接与短连接的区别。

1、TCP(传输控制协议)

可靠传输、面向连接、流控的传输协议。
优点:(可靠,准确) 缺点:慢。
例子:Web浏览器、电子邮件、文件传输程序

1、最上层是Source port(16)源端口号,Destination port(16)目端口号,
2、下一层是 Sequence number(32)序列号。主机到主机层,会把上层的数据进行分段,一段一段就需要区分,所以需要序列号。    为了保证在对端拿到数据的时候,数据段是有序的,进行重组和区分。
3、Acknowledgement number(32)三次握手的确认号,保证了可靠的传输行为,采用确认号进行确认。两端进行互相确认谁是谁。以免发送错误。

2、UDP(用户报文协议)

不可靠传输、尽力传递、面向无连接的传输协议。
优点:快   缺点:不可靠。
例子:域名系统(DNS)、视频流、IP语音(VoIP)

Checksum(16) 校验值 

4、端口号

1、源端口随机分配,目的端口使用知名端口
2、应用客户端使用的源端口号一般为系统中未使用的且大于1023
3、目的端口号为服务端应用服务的进程,如telnet 为23

5、三次握手

在正式连接之前,必须要进过TCP三次握手
1、主机A发送一个TCP报文给主机B,这个报文带有seq序列号,序列号是主机A随机生成的,比如100。ctl为特殊置位(任何的报文,底层成帧后,传输的是二进制1跟0的一段数字,其中有些部分是标记初始化的,SYN标示位上是二进制1,代表请求同步)
2、B接收到报文后,发现SYN=1位,说明是首次发起TCP连接打招呼的请求。B发送回去同时带有ctl=syn,ack(SYN置1以及ACK置1)的确认报文,同时序列号300也是本地随机产生的,并且ack确认号为对方发送过来的序列号+1(不一定是+1,加多少是根据报文长度)
3、当A收到B发来的报文,发现ack是100+1,确认是A发过去序列号是100的请求的报文的回报。A在给B发送序列号为100+1,ack为对方序列号+1的301的回报,ctl=ack

6、三次握手四次握手

通常情况下:一个正常的TCP连接,都会有三个阶段:1、TCP三次握手;2、数据传送;3、TCP四次挥手。注:以下说明最好能结合上图来理解。

SYN: (同步序列编号,Synchronize Sequence Numbers)该标志仅在三次握手建立TCP连接时有效。表示一个新的TCP连接请求。
ACK: (确认编号,Acknowledgement Number)是对TCP请求的确认标志,同时提示对端系统已经成功接收所有数据
FIN:
(结束标志,FINish)用来结束一个TCP回话.但对应端口仍处于开放状态,准备接收后续数据。

1)、LISTEN:首先服务端需要打开一个socket进行监听,状态为LISTEN. /* The socket is listening for incoming connections. 侦听来自远方TCP端口的连接请求 */

2)SYN_SENT: 客户端通过应用程序(比如CRT ssh连接Linux)调用connect进行active open。于是客户端(CRT)用tcp协议发送一个SYN以请求建立一个连接。之后客户端状态置为SYN_SENT. /*The socket is actively attempting to establish a connection.  在发送连接请求后等待匹配的连接请求 */

3)SYN_RECV: 服务端接收到报文后,发出ACK确认客户端的SYN,同时自己向客户端发送一个SYN。之后状态置为SYN_RECV /* A connection request has been received from the network. 在收到和发送一个连接请求后等待对连接请求的确认 */

4)ESTABLISHED: 代表一个打开的连接,双方可以进行或已经在数据交互了。/* The socket has an established connection. 代表一个打开的连接,数据可以传送给用户 *并应答服务器之前发送过来的SYN K ,也就是ACK K+1

中间传输数据略

5) 、FIN_WAIT1:客户端不想访问,主动关闭(active close)端应用程序调用close,于是其TCP发出FIN请求主动关闭连接,之后进入FIN_WAIT1状态./* The socket is closed, and the connection is shutting down. 等待远程TCP的连接中断请求,或先前的连接中断请求的确认 */

6)CLOSE_WAIT:服务端收到FIN请求后,被动关闭(passive close)端TCP,就发出ACK以回应FIN请求告诉客户端我收到结束请求。这时候服务端把FIN的请求作为文件结束符传递给,要结束的那个上层应用程序(比如ssh服务)客户端已经不想跟你连接了,你把这个客户端的ssh连接断开吧,并进入CLOSE_WAIT. /* The remote end has shut down, waiting for the socket to close. 等待从本地用户发来的连接中断请求 */

7)FIN_WAIT2: 客户端主动关闭端)接到服务器的ACK后,就进入了FIN-WAIT-2 ./* Connection is closed, and the socket is waiting for a shutdown from the remote end. 从远程TCP等待服务端再次发送,上层应用已经断连接的提示,连接中断请求 */

8)、LAST_ACK: 服务端(被动关闭端)一段时间后,接收到文件结束符的应用程序将调用CLOSE关闭连接(就是接收到了ssh反馈说我已经把这个客户端连接已经断开)。这导致它的TCP也发送一个 FIN,等待对方的ACK.就进入了LAST-ACK . /* The remote end has shut down, and the socket is closed. Waiting for acknowledgement. 等待原来发向远程TCP的连接中断请求的确认 */

9)、TIME_WAIT:在主动关闭端接收到FIN后,TCP就发送ACK包,并进入TIME-WAIT状态。/* The socket is waiting after close to handle packets still in the network.等待足够的时间以确保远程TCP接收到连接中断请求的确认 */

10)、CLOSING: 比较少见./* Both sockets are shut down but we still don’t have all our data sent. 等待远程TCP对连接中断的确认 */

11)、CLOSED: 被动关闭端在接受到ACK包后,就进入了closed的状态。连接结束./* The socket is not being used. 没有任何连接状态 */

增加解释:

TIME_WAIT状态的形成只发生在主动关闭连接的一方。
主动关闭方在接收到被动关闭方的FIN请求后,发送成功给对方一个ACK后,将自己的状态由FIN_WAIT2修改为TIME_WAIT,而必须再等2倍 的MSL(Maximum Segment Lifetime,MSL是一个数据报在internetwork中能存在的时间)时间之后双方才能把状态 都改为CLOSED以关闭连接。目前RHEL里保持TIME_WAIT状态的时间为60秒。

当然上述很多TCP状态在系统里都有对应的解释或设置,可见man tcp

关于长连接和短连接:
通俗点讲:短连接就是一次TCP请求得到结果后,连接马上结束.而长连接并不马上断开,而一直保持着,直到长连接TIMEOUT(具体程序都有相关参数说明).长连接可以避免不断的进行TCP三次握手和四次挥手.
长连接(keepalive)是需要靠双方不断的发送探测包来维持的,keepalive期间服务端和客户端的TCP连接状态是ESTABLISHED.目前http 1.1版本里默认都是keepalive(1.0版本默认是不keepalive的),ie6/7/8和firefox都默认用的是http 1.1版本了(如何查看当前浏览器用的是哪个版本,这里不再赘述)。一个应用至于到底是该使用短连接还是长连接,应该视具体情况而定。一般的应用应该使用长连接。

连接终止协议(四次挥手)
   由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
 (1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)。
 (2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
 (3) 服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)。
 (4) 客户段发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。
CLOSED: 这个没什么好说的了,表示初始状态。

LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。

SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

ESTABLISHED:这个容易理解了,表示连接已经建立了。

FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。

LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。
最后有2个问题的回答,我自己分析后的结论(不一定保证100%正确)

1、为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

2、为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为:虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

7、TCP滑动窗口机制

A发送B一个报文,就要通过TCP三次握手,会导致会很繁琐。如果A连续发送3个报文,就会节省很多时间,B收到后,在进行答复。但要求B的缓存能力要足够,足够处理3个报文。但是有些设备老旧,B只能处理2个报文,导致第三个报文丢失,B对A的发回来的报文进行确认后,A发现B的报文,ack是基于第二个包+1,也就是3,并且携带B窗口大小是2,下回A在给B发送请求,只发2个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值