TCP三次握手四次挥手

文章详细解释了TCP连接的三次握手过程,包括目的和必要性,以及SYN洪水攻击的原理。随后介绍了四次挥手,重点在于TIME_WAIT状态及其解决方法,如使用setsockopt中的SO_REUSEADDR选项。同时提到了保活计时器的作用。
摘要由CSDN通过智能技术生成

 

目录

1.三次握手

建立连接需要解决三个问题

三次握手过程

SYN洪水攻击

2.四次挥手

四次挥手过程

解决TIME_WAIT状态引起的bind失败的方法


1.三次握手

建立连接需要解决三个问题

1.使TCP双方能够确知对方的存在。

2.使TCP双方能协商一些参数(如最大报文段长度、最大窗口大小、时间戳选项等)。

3.使TCP双方能够对运输实体资源(如缓存大小、各状态变量、连接表中的项目等)进行分配和初始化。

三次握手过程

1.TCP服务器进程需要先创建传输控制块,用来储存TCP连接中的一些重要信息(例如TCP连接表、指向发送和接收缓存的指针、指向重传队列的指针以及当前发送和接受序号等)。之后,TCP服务器就进入监听状态(LISTEN),等待客户端进程的连接请求。实际上服务器几乎从不休息,所以一直都会处于监听状态等待客户端的连接。

2.TCP客户端在连接之前也需要创建传输控制块,然后向TCP服务器进程发送TCP连接请求报文段,并进入同步已发送(SYN-SENT)状态。注意,TCP规定SYN被设置为1的报文段不能携带数据,但是要消耗一个序号,也就是说如果这次发送序号为x,则客户端下次发送的报文的序号应该为x+1。

3.TCP服务器进程收到客户端TCP请求连接报文段后,如果同意连接,就向客户端发送TCP连接请求确认报文段(SYN和ACK都置为1),并进入同步已接收(SYN-RCVD)状态。这个报文的确认序号一定是x+1。假设服务器发送的请求确认报文段初始序号为y。

4.TCP客户端进程收到来自服务器的TCP连接请求确认报文段后,还需要向服务器进程发送一个普通的TCP确认报文段,并进入连接已建立(ESTABLISHED)状态。这个普通确认报文段要确认收到来自服务器进程的序号为y的报文,所以确认序号为y+1,表示服务器下次发送的报文序号应该为y+1,序号为x+1。TCP规定普通报文段可以携带数据,但如果不携带数据,则不消耗序号。

5.TCP服务器进程收到普通确认报文段后,就进入连接已建立(ESTABLISHED)状态。这时候一个TCP连接就建立成功了,双方就可以开始进行可靠的数据传输了。

这里有一个问题,为什么TCP客户进程最后还要发送一个普通的TCP确认报文段呢?这是否有些多余?答案是不多余。

想像这样一种场景,客户端主动发送一个SYN=1,SEQ=x(也就是序号,下面统一叫SEQ)的TCP连接请求报文段,但是该报文段在某些网络节点滞留了。这必然会导致该报文段的超时重传,假设重传的连接请求报文段被服务器正常接收到了。由于是“两次握手”,那么服务器在发送完SYN=1,ACK=1,SEQ=y,ack=x+1(ack就是确认序号)的TCP连接请求确认报文段后就会立即进入连接已建立(ESTABLISHED)状态,而不是像三次握手那样进入同步已接收状态(SYN-RCVD)。TCP客户端收到服务器发送的SYN=1,ACK=1,SEQ=y,ack=x+1的TCP连接请求确认报文段后也进入连接已建立(ESTABLISHED)状态,不给服务器发送普通确认报文段。那么这时双方都处于连接已建立状态,传输完数据后四次挥手释放连接,双方进入关闭状态。一段时间后,原先滞留的那个TCP连接请求报文兜兜转转终于到达服务器了。服务器会误以为客户端又发起了一个新的TCP连接请求,于是给TCP客户端进程发送TCP连接请求确认报文段,并进入连接已建立状态。客户端在收到服务器发来的TCP连接请求确认报文段后,会有些呆明明我没发起请求啊你给我发这个干嘛(没有创建相关数据结构,当然也不在同步已发送状态)?当然不会理会该报文段。然而TCP已经进入连接已建立状态,他认为新的TCP连接已经建立好,并开始等待TCP客户端发数据,这样会白白浪费TCP服务器进程所在主机的很多资源。

综上,为什么是三次握手而不是两次握手,这是为了防止已失效的TCP连接请求报文段突然又传送到了TCP服务器进程造成资源浪费

SYN洪水攻击

TCP连接过程中,服务器在接收到客户端发来的TCP连接请求报文后,会给客户端发送TCP连接请求确认报文,并进入同步已接收(SYN-RCVD)状态。由于服务器会给这些请求连接的客户端建立一个未连接队列,用来等待客户端的最后一次确认报文才从同步已接收状态进入连接已建立状态。然后就会删除未连接队列中该客户端信息。那么如果客户端(利用假IP)向服务器不断发送请求连接报文,服务器恢复确认请求包,并开始等待客户端确认。ip都不存在,自然不会有任何响应,所以服务器会一直超时重传。这些伪造的请求连接报文会长时间占用未连接队列,会导致服务器资源被消耗,无法对正常客户提供服务。

2.四次挥手

数据传输结束后,TCP通信双方都可以主动释放TCP连接。

四次挥手过程

1.假设TCP客户端进程通知服务器主动关闭TCP连接,TCP客户端会发送FIN=1,ACK=1的TCP连接释放报文段,并进入终止等待1(FIN-WAIT-1)状态。

2.TCP服务器进程接收到TCP请求释放报文段后,会发送一个普通的TCP确认报文段并进入关闭等待(CLOSE-WAIT)状态。TCP服务器进程这时应通知高层应用进程:“TCP客户进程要断开与自己的连接”。此时,从TCP客户进程到TCP服务器进程这个方向的连接就释放了。这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了,但是TCP服务器进程如果还有数据要发送,TCP客户端进程仍要接收,也就是说服务器到客户端的连接并未关闭。半关闭状态可能会持续一段时间。

3.TCP客户端收到确认报文后会进入终止等待2(FIN-WAIT-2)状态,然后开始等待服务器的TCP连接释放报文段。如果使用TCP服务器进程的应用进程已经没有数据要发送了,应用进程就通知其TCP服务器进程释放连接。

4.TCP服务器进程发送TCP连接释放报文并进入最后确认(LAST-ACK)状态。

5.TCP客户进程收到来自服务器的TCP连接释放报文后,会发送普通的确认报文,然后进入时间等待(TIME-WAIT)状态。

6.TCP服务器进程收到该普通的TCP确认报文段后就进入关闭(CLOSED)状态,TCP服务器进程撤销相应的传输控制块。而TCP客户进程还要经过2MSL后才能进入关闭(CLOSED)状态。MSL是最长报文段寿命(Maximum Segment Lifetime),[RFC793]建议为两分钟。也就是说,TCP客户端进程进入时间等待(TIME-WAIT)状态后,还有经过4分钟才能进入关闭(CLOSED)状态。这完全是从工程上来考虑的。对于现在的网络,MSL取为两分钟可能太长了,因此TCP允许不同的实现可根据具体情况使用更小的MSL值。经过2MSL时间后,TCP客户进程撤销相应的传输控制块后,就结束了这次TCP连接。

为什么TCP客户进程在时间等待(TIME-WAIT)状态必须等待2MSL的时间呢?

假如这里是“三次挥手”,TCP服务器进程发送TCP连接释放报文段后进入最后确认(LAST-ACK)状态。TCP客户进程收到该报文段后,发送普通的确认报文并进入关闭(CLOSED)状态而不是时间等待(TIME-WAIT)状态。然而,如果该确认报文丢失,这必然会造成服务进程对之前的TCP连接释放报文的超时重传,并仍处于最后确认状态。重传的TCP连接释放报文到达TCP客户端进程后,由于客户端进程处于关闭状态,因此不理睬该报文段,这必然会造成TCP服务器进程反复重传TCP连接释放报文段,并一直处于最后确认(LAST-ACK)状态而无法进入关闭状态并销毁相应传输控制块。

综上,处与时间等待状态(TIME-WAIT)后经过2MSL时长,可以确保TCP服务器进程能够收到最后一个TCP确认报文段而进入关闭(CLOSED)状态。

另外,TCP客户进程在发送完最后一个TCP确认报文段后,再经过2MSL时长,就可以使本次连接产生的所有报文段都从网络中消失,这样就能保证下一个TCP连接中不会出现旧连接中的报文段。

TCP保活计时器

除过时间等待计时器(2MSL计时),TCP还设有一个保活计时器来应对建立好的连接一方故障,而另一方毫无察觉的情况。保活计时器的具体做法是TCP服务器进程每收到一次TCP客户进程的数据,就重新设置并启动计时器(通常为两小时)。如果在保活计时器周期内没有收到TCP客户端发来的数据,则当保活计时器到时后,TCP服务器进程及巨响TCP客户进程发送一个探测报文段,以后每隔75秒发送一次。若连发十次都无响应,则认为TCP客户进程主机故障,于是关闭连接

解决TIME_WAIT状态引起的bind失败的方法

使用setsockopt函数。

在bind之前开启地址重复利用,optname参数选择SO_REUSEADDR选项可以使得不必等待TIME_WAIT状态消失就可以重启服务器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值