JHHK

欢迎来到我的个人网站
行者常至 为者常成

11、连接、释放连接

目录

快速开始

一、连接

三次握手及开始发送数据时
序号和确认号极其标志位的变化
客户端 SYN=1 ACK=0 seq=0 ack=0 len=0 发起连接请求
服务端 SYN=1 ACK=1 seq=0 ack=1 len=0 同意建立连接
客户端 SYN=0 ACK=1 seq=1 ack=1 len=0 我知道你同意了,下面我要开始发送数据了
客户端 SYN=0 ACK=1 seq=1 ack=1 len=k

握手阶段会交换:MSS/窗口大小/窗口缩放系数/初始序列号/是否支持选择确认
握手的目的是为了交换信息,以便实现可靠传输、流量控制、拥塞控制

为什么是三次握手的原因要明白
服务器一旦进入连接状态就没有超时断开了,因为他要一直等客户端发数据过来

TCP连接的四要素:源IP地址、源端口号、目标IP地址、目标端口号

二、释放连接

为什么是四次挥手

理解time-wait的作用

应用层可以关掉连接,TCP也可以关掉连接,但一般不用
http的Keepalive和 TCP的Keepalive 不是一回事

了解:closing状态 和 二三次挥手合并 的不同

连接

一、建立连接 - 三次握手

img

CLOSED:client处于关闭状态

LISTEN:server处于监听状态,等待client连接

SYN-SENT:表示client已发送SYN报文,等待server的第2次握手

SYN-RCVD:表示server接受到了SYN报文,当收到client的ACK报文后,它会进入到ESTABLISHED状态

ESTABLISHED:表示连接已经建立

0、初始状态
客户端的初始状态为CLOSED(关闭),服务器的初始状态为LISTEN(监听)

1、客户端发起连接请求(第一次握手)
SYN=1:代表同步;ACK=0:代表确认号无效;组合在一起:代表连接请求
seq=x:初始序号为x,将客户端的初始序号告知服务器;
发出连接请求后客户端进入SYN-SENT(同步已发送)状态,等待第二次握手

2、服务器确认连接请求(第二次握手)
SYN=1:代表同步;ACK=1:代表确认号有效;组合在一起:代表确认连接请求
seq=y:初始序号为y,将服务器的初始序号告知客户端;
ack=x+1:确认号为x+1,告知客户端已收到x个字节,请发送第x+1号字节
发出确认连接请求后服务器进入SYN-RCVD(同步已接收)状态,等待第三次握手

3、再次确认(第三次握手)
SYN=0:代表非同步;ACK=1:代表确认号有效; seq=x+1:发送第x+1号字节
ack=y+1:确认收到y个字节,请求发送第y+1号字节。

发出后客户端进入ESTABLISHED(连接已经建立)状态,当服务器收到第三次握手后也进入ESTABLISHED(连接已经建立)状态

二、前两次握手的特点

SYN都设置为1
代表第一次向对方发送数据

数据部分的长度都为0

TCP头部的长度一般是32字节
固定头部:20字节
选项部分:12字节

双方会交换确认一些信息
比如MSS、是否支持SACK、Window scale(窗口缩放系数)等
这些数据都放在了TCP头部的选项部分中(12字节)

握手阶段会交换:MSS/窗口大小/窗口缩放系数/初始序列号/是否支持选择确认
握手的目的是为了交换信息,以便实现可靠传输、流量控制、拥塞控制

握手阶段

三、疑问

1、为什么建立连接的时候,要进行3次握手?2次不行么?
主要目的:防止server端一直等待,浪费资源

2、如果建立连接只需要2次握手,可能会出现的情况
假设client发出的第一个连接请求报文段,因为网络延迟,在连接释放以后的某个时间才到达server
本来这是一个早已失效的连接请求,但server收到此失效的请求后,误认为是client再次发出的一个新的连接请求
于是server就向client发出确认报文段,同意建立连接
如果不采用“3次握手”,那么只要server发出确认,新的连接就建立了
由于现在client并没有真正想连接服务器的意愿,因此不会理睬server的确认,也不会向server发送数据
但server却以为新的连接已经建立,并一直等待client发来数据,这样,server的很多资源就白白浪费掉了

采用“三次握手”的办法可以防止上述现象发生
例如上述情况,client没有向server的确认发出确认,server由于收不到确认,就知道client并没有要求建立连接

3、第3次握手失败了,会怎么处理?
此时server的状态为SYN-RCVD,若等不到client的ACK,server会重新发送SYN+ACK包
如果server多次重发SYN+ACK都等不到client的ACK,就会发送RST包,强制关闭连接

四、客户端与服务端

如果有100个客户端与服务器通信,通常情况下会有100个独立的TCP连接,每个连接都是相互独立的,服务器需要为每个连接维护相应的状态。
每个TCP连接都由一个唯一的四元组(源IP地址、源端口号、目标IP地址、目标端口号)来标识。

释放连接

一、释放连接 - 四次挥手

img

FIN-WAIT-1:表示想主动关闭连接
向对方发送了FIN报文,此时进入到FIN-WAIT-1状态

CLOSE-WAIT:表示在等待关闭
当对方发送FIN给自己,自己会回应一个ACK报文给对方,此时则进入到CLOSE-WAIT状态
在此状态下,需要考虑自己是否还有数据要发送给对方,如果没有,发送FIN报文给对方

FIN-WAIT-2:只要对方发送ACK确认后,主动方就会处于FIN-WAIT-2状态,然后等待对方发送FIN报文

CLOSING:一种比较罕见的例外状态
表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文
如果双方几乎在同时准备关闭连接的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态
表示双方都正在关闭连接

LAST-ACK:被动关闭一方在发送FIN报文后,最后等待对方的ACK报文
当收到ACK报文后,即可进入CLOSED状态了

TIME-WAIT:表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可进入CLOSED状态了
如果FIN-WAIT-1状态下,收到了对方同时带FIN标志和ACK标志的报文时
可以直接进入到TIME-WAIT状态,而无须经过FIN-WAIT-2状态

CLOSED:关闭状态
由于有些状态的时间比较短暂,所以很难用netstat命令看到,比如SYN-RCVD、FIN-WAIT-1等

挥手阶段

二、释放连接 - 细节

TCP/IP协议栈在设计上,允许任何一方先发起断开请求。这里演示的是client主动要求断开
client发送ACK后,需要有个TIME-WAIT阶段,等待一段时间后,再真正关闭连接
一般是等待2倍的MSL(Maximum Segment Lifetime,最大分段生存期)
MSL是TCP报文在Internet上的最长生存时间
每个具体的TCP实现都必须选择一个确定的MSL值,RFC 1122建议是2分钟
可以防止本次连接中产生的数据包误传到下一次连接中(因为本次连接中的数据包都会在2MSL时间内消失了

如果client发送ACK后马上释放了,然后又因为网络原因,server没有收到client的ACK,server就会重发FIN
这时可能出现的情况是
client没有任何响应,服务器那边会干等,甚至多次重发FIN,浪费资源
client有个新的应用程序刚好分配了同一个端口号,新的应用程序收到FIN后马上开始执行断开连接的操作,本来
它可能是想跟server建立连接的

三、释放连接 - 疑问?

为什么释放连接的时候,要进行4次挥手?
TCP是全双工模式

第1次挥手:当主机1发出FIN报文段时
表示主机1告诉主机2,主机1已经没有数据要发送了,但是,此时主机1还是可以接受来自主机2的数据

第2次挥手:当主机2返回ACK报文段时
表示主机2已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的

第3次挥手:当主机2也发送了FIN报文段时
表示主机2告诉主机1,主机2已经没有数据要发送了

第4次挥手:当主机1返回ACK报文段时
表示主机1已经知道主机2没有数据发送了。

随后正式断开整个TCP连接

四、释放连接 - 抓包

有时候在使用抓包工具的时候,有可能只会看到“3次“挥手
这其实是将第2、3次挥手合并了

img

当server接收到client的FIN时,如果server后面也没有数据要发送给client了
这时,server就可以将第2、3次挥手合并,同时告诉client两件事
已经知道client没有数据要发
server已经没有数据要发了

几个问题

一、我们常常提到的长连接与短连接是如何区分的?

以socket为例,如果建立连接后我们立刻close就叫短连接,过一段时间后再close算长连接,是这样区分的吗?

长连接短连接并没有时间上的规定

短连接:连接成功 -> 拿数据(时间可长可短) -> 数据拿完断开连接
短连接就是做完数据交互马上断开连接

长连接:连接成功 -> 拿数据(时间可长可短) -> 等待 -> 拿数据(时间可长可短) -> 等待
长连接就是当需要频繁的跟服务器交互获取数据时,可以一直处于连接状态来节约建立连接断开连接的开销

长连接短连接是一种交互方式,是根据业务需要来决定的

服务器是否会一直保持连接
lxy:
服务器的一个服务通常对应的是多个客户端,在通讯时与每个客户端都会建立一个链接,
数据发送完毕之后通常都会断开当次连接以节省资源,再发送时在重新连接

但如果客户端不想断开连接时,服务端在15s(看具体设置)内收不到数据也会强制断开,以节省资源

客户端强制杀死进程会怎样

一般会在强制杀死前调用close以关闭连接
调用close就是发送FIN
这个图演示的是在杀死前发送了RST报文来通知服务端,RST用于表示发生了某种错误或异常情况,它是一种强制性的连接中断。

二、假设建立连接后,没有断开连接,这里服务器受影响的硬件是不是主要是网卡?
那具体会影响网卡的哪些性能呢?网速还是处理数据的速度?

要搞清楚这个问题,首先要搞清楚软件层面与硬件层面

软件层面
建立连接就是客户端创建一个socket对象,服务端创建一个ServeSocket,当一个客户端连接过来时为这个客户端分配一个socket对象, 客户端与服务端通过socket实例调用接口收发数据

img

只要连接不断开,这两个socket对象就在内存中,占用内存资源,与网卡没有关系

电脑的Mac地址就是网卡的Mac地址

硬件层面
网卡是二层网络设备工作在物理层和链路层,有数据发送时负责解析数据
所以只是建立连接没有数据发送时,对网卡是没有影响的。

网卡的作用:
检验数据包:看MAC地址是否是发送给自己的,不是就丢弃
带宽(bps):比如百兆网卡,千兆网卡,当数据传输速率大于带宽就会丢弃数据
网速和数据处理速度应该都是指带宽

三、假设数据太多,网卡已经接收不过来数据,直接丢弃,这时数据是不是只到了物理层,没有到达链路层?

img

网卡是二层网络设备,工作在物理层和链路层,数据能到达网卡(进行MAC校验,校验成功接收数据)就已经到达了链路层

网卡有一个缓冲区,数据过多缓冲区放不下时就会丢弃数据

四、

img


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.