TCP中的握手

2019-07-28  本文已影响0人  六弦极品

一、TCP层FLAGS标志字段

SYN: 表示建立连接
FIN: 表示关闭连接
ACK: 表示响应
PSH: 表示有 DATA数据传输
RST: 表示连接重置
URG: Urget pointer is valid (紧急指针字段值有效)

二、建立连接三次握手

A -->[SYN] --> B
A <--[SYN/ACK] <--B
A -->[ACK] -->B
(1) 客户端A 发送一个带SYN标志的TCP报文到服务器,这是三次握手过程中的报文1。
(2) 服务器B 回应客户端A, 这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯。
(3) 客户端A回应服务端B一个ACK报文,这是报文段3。

三、四次握手

A -->[FIN]-->B
A <--[ACK]<--B
A <--[FIN]<--B
A -->[ACK]-->B
(1) 客户端A主动向服务器B发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)
(2) 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)
(3) 服务器B被动关闭连接,向客户端A发送一个FIN(报文段6)
(4) 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)

四、TCP连接状态

CLOSED: 表示初始状态。
LISTEN: 表示服务器端的某个SOCKET处于监听状态,可以接受连接。
SYN_SENT: 表示客户端已发送SYN报文,等待服务端的发送三次握手中的第2个报文。
SYN_RCVD: 等待三次TCP握手过程中最后一个ACK报文完成发送。
ESTABLISHED:表示完成三次TCP握手,连接已经建立。
FIN_WAIT_1: 主动关闭连接,向对方完成发送了FIN报文。
CLOSE_WAIT: 被动关闭连接方收到FIN并完成发动ACK,等待自己发送FIN报文。
FIN_WAIT_2:主动关闭连接方收到ACK后的状态,表示半连接状态。
LAST_ACK: 被动关闭方发送FIN报文后,等待对方ACK报文。
TIME_WAIT: 表示主动方收到对方的FIN报文,并完成发送ACK报文,等2MSL后即可回到CLOSED可用状态。
CLOSING: 表示主动发送FIN后,没收到对方的ACK,反而先收到对方的FIN报文,双方几乎在同时close一个SOCKET的话,双方同时发送FIN报文的情况,即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

注:MSL(最大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现都必须选择一个确定的MSL值.RFC 1122建议是2分钟,但BSD传统实现采用了30秒.TIME_WAIT 状态最大保持时间是2 * MSL,也就是1-4分钟.
建立连接三次握手
关闭连接四次握手

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报文,并保证于此。

3、TIME_WAIT状态存在的理由:
(1) 可靠地实现TCP全双工连接的终止
(2) 允许老的重复标志分节在网络中消逝

TIME_WAIT : 双方建立TCP连接后,主动关闭连接的一方发送最后一个ACK后就会进入TIME_WAIT状态。这个状态会等待2MSL时间,才进入CLOSED状态。

查看当前系统下所有连接状态的数:
[root@vps ~]#netstat -n|awk '/^tcp/{++S[$NF]}END{for (key in S) print key,S[key]}'
TIME_WAIT 286
FIN_WAIT1 5
FIN_WAIT2 6
ESTABLISHED 269
SYN_RECV 5
CLOSING 1

如发现系统存在大量TIME_WAIT状态的连接,通过调整内核参数解决:
编辑文件/etc/sysctl.conf,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行 /sbin/sysctl -p 让参数生效。

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系默认的 TIMEOUT 时间

其它参数说明:
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
默 认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
上一篇 下一篇

猜你喜欢

热点阅读