【计网】TCP的三次握手及四次挥手详解

来源:互联网 发布:类似知否的古风宅斗文 编辑:程序博客网 时间:2024/05/21 07:49

引入

运输层连接有三个阶段

  • 连接建立(三次握手)
  • 数据传送
  • 连接释放(四次挥手)

三次握手原理

1.图解三次握手建立 TCP 连接的各状态

这里写图片描述

2.建立连接过程分析

(1)第一次握手

A 向 B 发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x。

(2)第二次握手

B 收到连接请求报文段后,同意A的请求,发回确认,B 在确认报文段中设置SYN = 1,ACK = 1,确认号ack = x+1,自己选择的序号 seq = y

(3)第三次握手

A收到此报文段后向 B 给出确认,设置 ACK = 1,确认号 ack = y +1,然后 A 通知上层应用进程,连接已经建立。

3.建立连接的状态转换分析

(1)第一次握手

  • 客户端:CLOSED–>SYN-SENT
    客户端之前处于关闭状态,需要传送数据时,向服务端发送建立连接请求,转换为SYN-SENT,表示建立连接请求报文段已发送。

  • 服务端:CLOSED–>LISTEN
    服务端之前处于关闭状态,由于服务端需要接收客户端发来的数据,所以转换为LISTEN状态,表示处于监听状态

(2)第二次握手

  • 客户端:SYN-SENT–>ESTABLISHED
    客户端接收到了服务端的请求报文,然后转换为ESTABLISHED状态,表示连接已建立。

  • 服务端:LISTEN–>SYN-RCVD
    服务端接收到了客户端的请求报文,也给客户端发送请求连接报文,之后等待客户端确认,转换为SYN-RCVD,表示已接收到客户端的请求。

(3)第三次握手

  • 客户端:SYN-SENT–>ESTABLISHED
    给服务端发送确认信息,然后转换为ESTABLISHED状态,表示连接已建立。

  • 服务端:SYN-RCVD–>ESTABLISHED
    接收到了客户端发来的确认之后,就转换状态为ESTABLISHED,表示已经建立连接。

4.建立连接中的几个问题

(1)第一次握手中的seq有什么作用,是不是固定的值?

答:序号seq可以保证有序性,当序号达到最大值时(2的32次方:大约4G),可以重用,这个初始序号会随时间而改变,因此每一个连接都拥有不同的初始序列号(防止重叠),这样也保证了安全性,若序号是固定值,则很容易被伪造,从而打断TCP的正常连接。

(2)为什么第二次握手中的ack=x+1?

答:因为第一次握手中的SYN请求报文段不携带数据,但要消耗一个序号,所以ack=x+1。

(3)为什么不是两次握手?

答:防止已失效的连接请求报文段重连,还会浪费服务器资源,因为失效的报文段会创建文件描述符从而消耗内核结构体。

四次挥手原理

1.图解四次挥手释放 TCP 连接的各状态

这里写图片描述

2.释放连接过程分析

(1)第一次挥手

A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的 FIN = 1,其序号seq = u,等待 B 的确认

(2)第二次挥手

B 发出确认,确认号 ack = u+1,而这个报文段自己的序号 seq = v。TCP 服务器进程通知高层应用进程。从 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭状态,B 若发送数据,A 仍要接收。

(3)第三次挥手

若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接,请求关闭连接标志位FIN=1,ACK=1,确认上一个报文已收到,可能还有数据发送,所以seq=w,确认号ack=u+1不变。

(4)第四次挥手

A 收到连接释放报文段后,必须发出确认,在确认报文段中 ACK = 1,确认号 ack=w+1,自己的序号 seq = u + 1。

3.释放连接的状态转换分析

(1)第一次挥手

  • 客户端:ESTABLISHED–>FIN-WAIT-1
    客户端之前处于建立连接状态,当不需要传送数据时,向服务端发送关闭连接请求,转换为FIN-WAIT-1,表示请求关闭连接报文段已发送。处于等待关闭状态。

  • 服务端:ESTABLISHED–>CLOSE-WAIT
    服务端之前处于建立连接状态,由于客户端不需要给服务端发送数据了,并且向服务端发送了关闭连接请求,但这时候服务端可能还要向客户端发送数据,所以是半关闭状态,转换为CLOSE-WAIT状态,表示处于等待关闭状态。

(2)第二次挥手

  • 客户端:FIN-WAIT-1–>FIN-WAIT-2
    客户端接收到了服务端的确认报文,然后转换为FIN-WAIT-2状态,表示处于等待服务端关闭连接状态。

  • 服务端:ESTABLISHED–>CLOSE-WAIT
    服务端给客户端发送确认报文,转换为CLOSE-WAIT,表示处于等待关闭状态。

(3)第三次挥手

  • 客户端:FIN-WAIT-2–>TIME-WAIT
    客户端收到了服务端的请求关闭连接报文,转换为TIME-WAIT,等待2MSL就关闭连接,表示处于TIME-WAIT状态。

  • 服务端:CLOSE-WAIT–>LAST-ACK
    这时候服务端没有数据要给客户端发送了,就请求关闭与客户端的连接,但还要等待客户端的确认,所以就转换为LAST-ACK状态,表示处于等待客户端的确认状态。

(4)第四次挥手

  • 客户端:FIN-WAIT-2–>TIME-WAIT
    客户端给服务端发送确认报文,之后转换为TIME-WAIT,等待2MSL就关闭连接,表示在TIME-WAIT状态之后就处于CLOSED状态。

  • 服务端:LAST-ACK–>CLOSED
    接收到了客户端发来的确认报文之后,就转换为CLOSED状态,表示处于关闭连接状态。

4.释放连接中的几个问题

(1)为什么第二次挥手没有FIN?

答:因为TCP是全双工的,服务端可能还要给客户端发送数据。

(2)为什么第三次挥手中还需要ACK=1

答:因为要给客户端通知已经收到了上一次的数据,虽然数据传送客户端的确认由内核(OS)完成。

(3)第四次挥手之后,为什么需要等待2MSL,等待时间是否可以调整(调大或调小有什么影响)?

答:

  • 因为要可靠地实现TCP全双工连接的终止(若最后一次ACK丢失,重发可能丢失的ACK报文)
  • 允许老的重复分组在网络中消逝(TCP防止某个连接的老的重复分组在该连接终止后再现),即保证被重新分配的socket不会受到之前残留的延迟重发报文影响,防止某个连接的重复报文在连接终止后出现。
  • Windows下默认为4分钟,即240秒

(4)若出现大量TIME-WAIT状态的原因及解决方法?

答:

原因:TIME_WAIT状态下的socket不能被回收使用.

  • 对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 这将会占用内存,消耗CPU。

解决方法: 查看当前time_wait的数量 netstat -an | grep TIME_WAIT | wc -l

  • Windows:

    在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,添加名为TcpTimedWaitDelay的DWORD键,设置为60,以缩短TIME_WAIT的等待时间

  • Linux:

    • 1)通过调整内核参数解决,vi /etc/sysctl.conf,增加或修改如下参数
      net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies,可防范少量SYN攻击
      net.ipv4.tcp_tw_reuse = 1 表示开启TIME-WAIT sockets重用
      net.ipv4.tcp_tw_recycle = 1 开启TCP连接中TIME-WAIT sockets的快速回收
      net.ipv4.tcp_fin_timeout = 30 修改系統默认的 TIMEOUT 时间
      执行 /sbin/sysctl -p 让参数生效,查看系统的tcp参数情况:sysctl -a|grep tcp
    • 2)还可以设置/etc/sysctl.conf下的net.ipv4.ip_local_port_range的参数至少为1024 65535

TCP 的有限状态机

这里写图片描述

注:红色箭头表示对客户进程的正常变迁,蓝色箭头表示对服务器进程的正常变迁,黑色箭头表示异常变迁。

小疑问

1.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

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

2.服务端主动断开连接之后,可以立即使用原来的端口重新连接吗?

答:不能,立即重连产生异常,因为该端口已被占用,TIME-WAIT时间还没到,产生的“分身”会在2MSL之后消亡。

3.当输入端口号为0或-1(负数)时会出现异常吗?

答:当端口号为负数会出现异常,负数会报IllegalArgumentException:port out of range异常,0-1023是熟知端口,可能会出现BindException: Address already in use: bind,所以我们一般使用1024-65535之间的端口号。

4.半连接队列与全连接队列是什么?

在linux系统内核中维护了两个队列:syns queue和accept queue

  • syns queue
    用于保存半连接状态的请求,其大小通过/proc/sys/net/ipv4/tcp_max_syn_backlog指定,一般默认值是512,不过这个设置有效的前提是系统的syncookies功能被禁用。互联网常见的TCP SYN FLOOD恶意DOS攻击方式就是建立大量的半连接状态的请求,然后丢弃,导致syns queue不能保存其它正常的请求。

  • accept queue
    用于保存全连接状态的请求,其大小通过/proc/sys/net/core/somaxconn指定,在使用listen函数时,内核会根据传入的backlog参数与系统参数somaxconn,取二者的较小值。
    如果accpet queue队列满了,server将发送一个ECONNREFUSED错误信息Connection refused到client。

5.SYN攻击是什么及解决办法?

答:

(1)概念
SYN攻击属于DOS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。
(2)检测
使用Linux命令 netstat -n -t | grep SYN_RECV | wc -l 查看处于SYN_RECV状态的连接数
(3)解决方法

  • 过滤网关防护
    • 网关超时设置:防火墙设置SYN转发超时参数,该参数远小于服务器的timeout时间
    • SYN网关:CS通过SYN网关发SYN包,当客户端确认包到达时,如果有数据则转发,否则丢弃。
    • SYN代理:不转发SYN包,而以服务器的名义主动回复SYN/ACK给客户,若收到ACK包,正常访问。
  • 加固tcp/ip协议栈
    • SynAttackProtect机制:关闭某些socket选项,使系统能处理更多的SYN连接
    • 增加最大半连接数:Linux下用变量tcp_max_syn_backlog定义backlog队列容纳的最大半连接数
    • SYN cookies技术:当半连接队列满时,SYNcookies不丢弃SYN请求,而通过加密技术来标识半连接状态



本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文

参考资料:《计算机网络 第六版》-谢希仁

TCP连接的状态详解以及故障排查

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 玩王者荣耀手机屏幕竖着怎么办 棉被被老鼠尿湿怎么办 打完子弹能下来怎么办 怪物猎人 弩子弹打完了怎么办 烤瓷牙龈发黑了怎么办 做彩超前喝水了怎么办 胸贴过敏红痒怎么办 芡粉里面有虫了怎么办 勾芡淀粉放多了怎么办 剁排骨没有好刀怎么办 硬币掉进档位里怎么办 魅族mx5手机太卡怎么办 华为m9手机声音小怎么办 放卡的地方堵住怎么办 美图m8蓝屏了怎么办 美图m8手机蓝屏怎么办 美图m6s手机白屏怎么办 魅蓝2开不开机怎么办 魅族手机主键没反应怎么办 魅族手机主键失灵怎么办 手机4g网络不稳定怎么办 华为m9收不到手机信息怎么办 华为手机wifi信号弱怎么办 手机连接wifi信号差怎么办 华华为p10信号不好怎么办 烟没拆封受潮了怎么办 和亲儿子发生了性关系怎么办 无心磨磨出来圆度不好怎么办 中国人在越南办结婚证怎么办? 无线网被限速了怎么办 联通大王卡上传速度慢怎么办 小米手机下载视频速度慢怎么办 大疆御air脚架断了怎么办 大疆飞行器线断了怎么办 移动校园卡套餐到期后怎么办 流量年包到期了怎么办 家里无线网信号不好怎么办 无线网光信号红灯了怎么办 机顶盒获取不了lp地址怎么办 32内存卡丢了怎么办 手机上的相机找不到了怎么办