-
TCP建立连接3次握手
握手过程如下:
客户端A向服务器发送TCP连接请求数据包,报文设置同步标志位SYN=1,客户端序号seq=x(表明传输数据时的第一个数据字节的序号是x),A然后进入SYN-SENT状态;
服务器B收到连接请求后,发回连接确认数据包,报文设置同步标志位SYN=1,服务端序号seq=y,以及对客户端的确认号ack=seq(A)+1=x+1,B然后接入SYN-RCVD状态;
-
客户端A收到服务器B的确认数据包后,进一步做确认,发送一个SYN=0,seq=x+1,ack=seq(B)+1=y+1的确认报文,A然后进入数据传输状态ESTABLISHED,服务器B收到客户端A的确认报文后也进入数据传输状态ESTABLISHED;
那为什么只是3次握手呢?
举个随便找人聊天的例子:A对B说:喂,你听得到我说话吗? B对A回:嗯,我听到的你说话,你听得到我说话吗? A回B说:可以听到,我们开始聊天把! BABALA的聊天
应该把网络状态想象为不可靠的,3次握手可以保证任何一次握手出现问题都可以发现或补救:
第一次握手A发送SYN传输失败,A,B都不会申请资源,连接失败。如果一段时间内发出多个SYN连接请求,那么B只会接受它最后发送的那个SYN的SYN+ACK回应,忽略其他回应全部回应,B中多申请的资源也会释放;
第二次握手B发送SYN+ACK传输失败,A不会申请资源,B申请了资源,但收不到A的ACK,过一段时间释放资源。如果是收到了多个A的SYN请求,B都会回复SYN+ACK,但A只会承认其中它最早发送的那个SYN的回应,并回复最后一次握手的ACK;
第三次握手ACK传输失败,B没有收到ACK,释放资源,对于后序的A的传输数据返回RST。实际上B会因为没有收到A的ACK会多次发送SYN+ACK,次数是可以设置的,如果最后还是没有收到A的ACK,则释放资源,对A的数据传输返回RST。
数据传输
-
TCP释放连接4次握手
四次握手过程如下:
客户端A主动关闭连接,A发送一个终止标志位FIN=1,客服端序号seq=u的数据包到服务器B,然后A进入FIN-WAIT-1状态,表示A没有数据要传输给服务器B,此时A处于半连接状态;
服务器B收到FIN数据包,就返回一个ACK,同意关闭连接,seq=v,确认号ack=u+1,此时服务端B进入CLOSE-WAIT状态;
客户端A收到这个数据包后,进入FIN-WAIT-2状态,此时仍然可以接收服务器B发送过来的数据包;
-
服务器B没有数据数据要传输给客户端A,也发送一个一个终止标志位FIN=1,seq=w,ack=u+1的确认数据包,尔后进入LAST-ACK状态。客户端A收到服务器B的FIN关闭确认数据包后,给服务器B发回一个确认包,seq=u+1,ack=w+1,进入TIME-WAIT状态,等待2MSL时间后进入CLOSED状态,服务器B接收到客户端的ACK确认报文后进入CLOSED关闭状态,此时服务器B若没有收到这个ACK,服务器B的超时重传机制会重新发送一个关闭确认数据包。
问答:
那为什么是4次握手呢?
答:因为TCP是全双工通信,每个方向上都要进行单独关闭,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。-
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间 Maximum Segment Lifetime)才能返回到CLOSE状态?
答:- 为了保证主动关闭方的最后一个ACK报文能够到达被动关闭方,假设这个ACK报文丢失了,处于LAST-ACK状态的被动关闭方在规定的时间内没有收到这个ACK报文,或超时重传FIN报文,而主动关闭方在等待2MSL时间内收到这个重传的报文会重新回复一次确认,重新启动2MSL计时器。如果主动关闭方在TIME-WAIT状态内不等待2MSL的话,就无法收到重传报文。
- 主动关闭方在等待2MSL时间后,可以使得本连接持续时间每产生的所有报文都过期了,使得下一次新的连接不会出现旧的连接报文。
-
为什么会出现大量的CLOSE-WAIT状态的连接,如何解决?
答:- 产生原因
- CLOSE_WAIT产生的原因是主动关闭方主动关闭,被动关闭方收到FIN包,应用层却没有做出关闭操作引起的。也就是说,在被动关闭连接情况下,在已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。
- 出现大量CLOSE_WAIT的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。
- 解决方案
- 通过优化系统内核参数可容易解决
vi /etc/sysctl.conf #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒 net.ipv4.tcp_keepalive_time=1200 #生效,如下命令 /sbin/sysctl -p
- 需要从程序本身出发
- 可以使用TCP的keepalive功能,让操作系统替我们自动清理掉CLOSE_WAIT连接
- 通过优化系统内核参数可容易解决
- 产生原因
-
为什么会出现大量的TIME-WAIT状态的连接,如何解决?
答:- 产生原因
在通讯过程中A主动关闭造成的, 在A发送了最后一个FIN包后,系统会等待 Double时间 的MSL(Max Segment Lifetime)【注:按不同的操作系统有不同时间】用于等待接受B发送过来的FIN_ACK和FIN, 这段时间A的对应的socket的fd是不能够重新利用的, 这样在大量的短连接服务中,会出现TIME_WAIT过多的现象。 - 解决方法
-
通过优化系统内核参数,调整TIME_WAIT超时时间
vi /etc/sysctl.conf #表示开启SYN Cookies。 #当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭 net.ipv4.tcp_syncookies = 1 #表示开启重用。 #允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 #表示如果套接字由本端要求关闭。 #这个参数决定了它保持在FIN-WAIT-2状态的时间 #生效,如下命令 /sbin/sysctl -p
-
- 产生原因
TCP的3次握手和4次挥手协议及数据传输过程
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 最近在恶补计算机网络方面的知识,之前对于TCP的三次握手和四次分手也是模模糊糊,对于其中的细节更是浑然不知,最近看...