一、TCP的三次握手及相关问题
1. TCP报文段首部格式
TCP报文段首部格式
-
序号seq(sequence number): 表示本报文段所发送的数据的第一个字节序号
- 比如序号字段值是301,携带的数据共有100个字节,表示本报文段数据的第一个字节的序号是301
-
确认号ack(acknowledge number):表示期望收到对方下一个报文段的第一个数据字节的序号
- 比如 B收到A发来的报文中:
- 序号的字段值是501(序号表示的是数据的第一个字节序号),数据长度是200
- 则:B收到了序号为501-700的数据---->说明 B期待收到的下一个数据的序列号应该是 701
- 于是:B把返回给A的报文中 确认号(ack)设置为701
- 比如 B收到A发来的报文中:
-
确认ACK(AXKnowlegment): 仅仅当ACK为1时该字段才有效,建立连接后所有传送的报文段都必须把ACK置1
-
同步SYN(Synchronize Sequence Numbers) 在建立连接时用来同步序号
- SYN=1 ACK=0 表示是连接请求报文段
- SYN=1 ACK=1 表示对方同意建立连接
-
终止FIN(FINis) 用来释放一个连接
- FIN = 1时表示要求释放连接
2. tcp三次握手详解
三次握手
- 客户端的初始状态是 closed
- 服务端的初始状态是 listen
2.1 第一次握手
客户端给服务端发送请求报文段
- 此报文段的同步位 SYN = 1 ,表示这是一个请求报文段
- 随机生成一个序列号 seq = x;
- 随机生成一个序列号是为了网络安全,如果序列号不是随机的容易被黑客获取到初始序列号
- 客户端的状态变成: SYN_SEND(同步已发送)
- 这个报文段不能携带数据
2.2 第二次握手
服务端同意建立连接
- SYN = 1 , ACK = 1 表示同意建立连接
- 确认号是 ack = 1 ;
- 随机生成一个初始序号 seq = y;
- 不携带数据
- 服务端状态变成 SYN_RCVD(同步已收到)
2.3 第三次握手
客户端再次向服务端给出确认
- AXK = 1
- 确认号 ack = y + 1 ; seq = x + 1 ;
- 客户端状态变成 ESTABLISHED
- 当服务端收到确认后也变成 ESTABLISHED
3. 为什么要三次握手,三次握手功能
三次握手功能生动解释- 第一次握手可以确认: 客户端发送数据功能正常 (A发出信号)
- 第二次握手可以确认: 服务端接收和发送功能均正常(B确认喜欢A,并发出信号)
- 第三次握手可以确认: 客户端接收功能正常(第三个阶段才能确认A也喜欢B,第一个阶段并不能确认A喜欢B,第一个阶段A只是问了B)
4. 半连接队列和全连接队列
[图片上传失败...(image-e1545c-1578234377605)]
- 第一次受到client的SYN之后,server处于SYN_RCVD状态,此时双方还没有完全建立连接,server会把这种状态下的请求连接放在一个队列里,称为半连接队列
- 已经完成三次握手之后,建立起的连接会放在全连接队列中,如果队列满了可能会出现丢包,这样的队列称为全连接队列
- server发送SYN和ACK包的重传:服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s......
5. 三次握手中可以携带数据吗
第一次和第二次握手不可以携带信息,第三次可以携带信息,前两个阶段不可以携带信息。因为第三次握手的时候客户端才是ESTABLISHED状态,就上面那个生动的图来讲,只有第三次握手你确定了互相喜欢才可以携带一些信息(比如一起看电影、约会)
6. SYN 和 SYN 攻击
SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来海量的请求连接的第一个握手包(SYN包),被攻击服务器回应第二个握手包(SYN+ACK包),因为对方是假冒IP,对方永远收不到包且不会回应第三个握手包。导致被攻击服务器保持大量SYN_RECV状态的“半连接”,并且会重试默认5次回应第二个握手包,塞满TCP等待连接队列,资源耗尽(CPU满负荷或内存不足),让正常的业务请求连接不进来。
TCP的四次挥手及相关问题
1. 四次挥手详解
四次挥手
1.1 第一次挥手
client发出连接释放报文段
- FIN = 1 (要求释放连接)
- seq = u 前面传输数据的最后一个字节加1
- client状态:FIN_WAIT1(终止等待1、等待server确认)
1.2 第二次挥手
server接收到释放报文段后发出确认 (这时候 client ---> server方向连接断了)
- ACK = 1
- ack = u + 1 ;
- seq = v ; 已经发送的数据的最后一个字节序号加1
- server 进入CLOSE_WAIT(等待关闭状态)
- client 进入FIN_WAIT2(终止等待2状态),等待server发出释放确认报文段
- 这时候CLIENT-SERVER的连接释放了,这时候与的TCP处于办关闭状态(half-close),这时候client已经没有数据要发了,但是这时候server还有可能向client发送数据
1.3 第三次挥手
这时候server发出连接释放报文段(想让 server--->client方向连接断掉)
- FIN = 1;
- 重复发送确认报文段: ACK = 1; ack = u + 1;
- server状态: LAST_ACK 等待A确认
1.4 第四次挥手
client同意与server断开连接
- ACK = 1;
- client状态: TIME_WAIT 在2MSL之后变成CLOSED
- server状态: CLOSED
1.5 通俗解释一下
四次挥手
2. 为什发送端需要等待 2MSL后关闭
MSL:(Maximum segment lifetime)最长报文寿命
为什么要等待两个msl?
-
1.保证client发送的ACK可以成功到达server,如果client发送完就close了,万一报文丢失,server收不到client发来的ACK,就会超时重新进行第三次挥手,这个时间就是2MSL:即:超时等待时间+再次进行第三次挥手的事件
-
2.防止“已失效的连接请求报文段”出现在本连接中。
客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段
3. 为什么第二次挥手和第三次挥手不能合并
细心的同学发现,所谓四次挥手中的第二次和第三次就是把握手中的第二次拆来了。为什么不能合并?
- 因为挥手过程和握手过程不同,前两次握手是不携带数据的只处理连接问题。挥手不仅要解决连接问题,还要解决数据传输问题,第二次挥手后,client只是不能发送数据了,但是并不说明不能接受数据。server可能还有数据要给client。所以二三两次不可以合并
引用博客
- 本篇博客主要是在这篇博客基础上的修改:https://segmentfault.com/a/1190000020610336#item-1-4
- 参考文档
- https://blog.csdn.net/u014507230/article/details/45310847
- https://blog.csdn.net/lengxiao1993/article/details/82771768
- https://blog.csdn.net/qq_36865108/article/details/84885506
- https://www.jianshu.com/p/7d0f91345483
- https://cloud.tencent.com/developer/article/1115567
- https://blog.csdn.net/wudiyi815/article/details/8505726
- http://jm.taobao.org/2017/05/25/525-1/
- https://www.jianshu.com/p/bbb6261cb13e
- 书本才是最权威易懂的
- 《谢希仁计算机网络第六版》
- 转载标明链接哦
网友评论