字段 | 含义 |
---|---|
URG | 紧急指针是否有效。为1,表示某一位需要被优先处理 |
ACK | 确认号是否有效,一般置为1。 |
PSH | 提示接收端应用程序立即从TCP缓冲区把数据读走。 |
RST | 对方要求重新建立连接,复位。 |
SYN | 请求建立连接,并在其序列号的字段进行序列号的初始值设定。建立连接,设置为1 |
FIN | 希望断开连接。 |
三次握手
首先先说一下ACK和ack的区别,它们一个是确认值(Acknowledgement)ACK,为1表示确认连接;一个是确认编号(Acknowledgement Number),即受到对方主机传过来的seq序列号+1,提示对方我已经成功接收了你上一次发送过来的数据。
(1)客户端发送SYN报文到服务端,并指明自己的seq序列号为x,客户端进入syn-send状态
(2)服务端收到报文后,也会发送自己的SYN报文,以及确认值ACK=1,并指明自己的序列号seq为y,确认ack编号为x+1,表示自己接收到了客户端的连接请求,服务端进入syn-recv状态
(3)客户端收到服务端报文后,发送ACK报文确认连接,并发送自己的seq为x+1(上次是x,这次+1),ack为y+1,客户端服务端都进入established状态,连接建立成功,可以进行数据传输。
四次挥手
发出断开连接请求的可以是服务端也可以是客户端,下面就以客户端发出断开请求为例
(1)客户端发出FIN连接断开报文,序列号seq为u,客户端进入fin-wait-1状态
(2)服务端发送ACK确认,服务端seq=v,ack=u+1,服务端进入close-wait状态,客户端进入fin-wait-2状态
(3)服务端会继续发送数据给客户端,当数据发送完毕后,服务端会发送FIN和ACK报文,seq=w,ack=u+1,此时服务端进入last-ack状态
(4)客户端收到FIN报文后会发送ACK报文,服务端收到后会进入close关闭连接;而客户端会进入TIME-WAIT状态,时长为2MSL(max segment lifeTime),之后才会进入关闭状态
1.为什么三次握手不是两次?
假如是两次握手,客户端发送syn报文请求与服务端建立连接,但是服务端没有收到,那么客户端没有收到SYN+ACK确认报文,一段时间后会再次发送syn报文,这次服务端收到了,并回复了ACK报文,此时连接建立;当数据传输完毕,断开连接后,如果第一次发送的syn报文只是因为某些原因滞留了,此时才到达服务端,那么服务端以为是客户端又要再次与它建立连接,就会回复SYN+ACK报文,但是客户端知道自己没有发送,那么就不会应答,此时虽然客户端没有建立连接,服务端却认为连接已经正常建立了,就会一直等待客户端发送数据,浪费资源。
2.三次握手中可以携带数据吗?
在第一、二次握手中没有携带数据,第三次是可以的。假如在第一次握手请求时,可以携带数据,那么如果有人想恶意攻击服务端,就有可能可以发送大量携带数据的SYN请求,并不理会服务端是否正常接收,从而让服务端花费更多的时间和空间处理这些数据。但是在第三次握手请求发出后,客户端状态已经变成了established,可以携带数据。
3.syn攻击是什么?
当客户端发送syn请求后,服务端会将其发在一个半连接队列中,syn攻击就是在短时间内伪造大量不存在ip想服务端发送syn请求,服务端需要回复确认请求,由于伪造ip不存在,无法完成第三次握手,那么服务端会不断重试,发送SYN+ACK确认请求,导致半连接队列被伪造的SYN连接长时间占用,而正常的SYN请求由于半连接队列满了被丢弃,从而发送网络阻塞瘫痪。
检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。我们可以缩短SYN超时时间,增加半连接队列长度,使用网关过滤、SYN cookies技术等。
4.为什么握手是3次,挥手是4次?
当握手时收到SYN报文时,可以立即发送SYN+ACK报文用以确认连接;但是在挥手时,一方发起FIN请求报文后,另外一方可能还有未发送的数据,所以此时只能发送ACK确认报文,待后续数据发送完成后,才能发送FIN+ACK关闭连接确认,要分成两次发送,所以要4次。
5.4次挥手时最后等待2MSL是为了什么?
MSL指的是max segment lifeTime 报文在传输过程中的最长生存时间。(1)四次挥手最后发出的ACK确认报文对方可能没有收到,那么对方可能会重发FIN报文,那么就需要等待一段时间用以确保该ACK报文对方已经收到;如果在该时间段内又收到了FIN报文,那么还会再次发送ACK报文,并将等待时间重置未2MSL(2)此外,等待2MSL也是为了防止本次连接中有数据传输没有收到,用来等它们都消失,从而是下次连接时,不会存在本次发送的数据。
6.如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。