TCP的三次握手和四次挥手

tcp是一种传输层通信协议,一个TCP连接通常分为三个阶段:连接,数据传输和关闭,通过三次握手来建立一个连接,四次挥手断开一个连接

目录

  • TCP报文头部介绍
  • 三次握手建立连接
  • 四次挥手断开连接
  • TCP的特点及使用场景
TCP报文头部介绍

TCP报文头部由以下几部分构成:

  1. 源端口号
  2. 目标端口号
  3. 序列号
  4. 确认号
  5. 头部长度
  6. 六个标志位
  7. 窗口大小
  8. 校验和
  9. 紧急指针
  10. TCP头部选项
源端口号(16位)

标示报文的来源(客户端产生临时端口号)

目标端口号(16位)

标示报文的目的地(服务端指定端口号)

序列号(32位)

保证服务端接收到所有数据后能按正确顺序拼接起来,该序列号是由系统初始化的一个随机值ISN,一个报文的序列号=ISN+这个报文携带的数据的第一个字节的偏移量。
例子:要发5个报文,第一个报文的第一个字节的偏移量为0,序列号就是ISA+0;第一个报文携带的数据大小是1kb(1024),所以第二个报文的第一个字节的偏移量就是1024,序列号就是ISA+1024,以此类推。
(注意实际上三次握手时是会占据一个序列号的,所以实际上正式发送数据时第一个报文的序列号是ISA+1+0,这里为了方便理解就不考虑三次握手时占据的那个序列号)。

确认号(32位)

服务端收到客户端发来的报文后需要给客户端回复一个ack数据包,告诉客户端数据已经收到。回复报文的确认号=服务端收到的报文的序列号+1。
例子:服务端当前收到的报文的序列号是ISN+2048,那么它回复客户端的报文的确认号的值就是ISN+2048+1,其作用就是告诉客户端ISN+2048+1之前的所有数据都已经收到了。
注意这里的所有数据指的是:服务端回复ack时,必须要确保确认号之前的数据全部已经收到了,比如上面的例子,如果序列号是ISN+2048的报文收到了,但是ISN+1024的报文还没收到,那就不能回复ISN+2048+1的ack。

头部长度(4位)

TCP头部长度是以32位(4个字节)为一个单位。前面20个字节是固定的,TCP头部最小也就是20个字节。而头部长度就是用来描述这个TCP头部包含多少个单位。最多包含15个单位(头部长度四个字节最大可以表示到十进制的15)

六个标志位(每个标志占1位,每个标志只有0和1两种状态)

URG:为1时表示紧急指针有效。
ACK:为1时表示确认号是有效的,携带ACK标志的报文段也称确认报文段。
PSH:为1时是提示接收端应用程序应该立即从TCP接受缓冲区中读走数据,为后续接收的数据让出空间。
RST:为1时表示通知对方关闭连接或重新建立连接。带RST标志的TCP报文段也叫复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。发送完RST报文后TCP连接就关闭了,所以接收端收到RST报文后也就没有必要发送ACK包来确认了。
SYN:为1表示建立一个连接,携带SYN标志的报文段为同步报文段。SYN标志位只有在TCP建立连接时(也就是三次握手的时候)才会被置为1,目的在提醒服务端或客户端记住对方的起始序列号。
FIN:为1时用来告知对方本端要关闭连接了。

窗口大小(16位)

可以理解为自己接收数据的缓冲区大小,这个值在于告诉对方自己现在所能接收的最大数据量,如果对方发送的数据量超过这个值,那么这个数据将被丢弃。若这个最大数据量的值为0,那么对方会暂时停止发送数据,直到窗口大小大于0才恢复发送

校验和(16位)

这是一种对传输数据安全保障的签名机制,发送端对TCP报文(包括TCP头部和数据部分)执行CRC算法得到校验和,接收端收到报文后对报文执行同样的算法,将结果与校验和进行比对,两者一致说明TCP报文段在传输过程中没有损坏,如果不一致那么这段TCP报文段会被直接丢弃。

紧急指针(16位)

只有当URG标志位为1时紧急指针才是有意义的,紧急数据是不进入缓存区的。紧急指针的值其实是一个相对于序列号的偏移量,它标示了哪段数据是紧急数据。
例子:紧急指针的值是5,如果这个报文段的序列号seq=10,那就表示紧急指针指向的是15这个位置的字节,这就意味着10到14这段数据是紧急数据。

TCP头部选项

TCP头部选项最多包含40个字节,典型的TCP头部选项包含kind、length和info三个部分,kind表示选项的类型,length表示选项的长度,info表示选项的具体内容。

三次握手建立连接

三次握手

第一次握手:

客户端初始化产生了随机序列号ISN=x,将携带着SYN=1以及序列号seq=x的连接报文发送给服务端请求连接(第一次握手需要消耗一个序列号)

第二次握手:

服务端收到客户端发来的连接报文,查看SYN标志为1,于是将seq=x序列号保存到服务端(表示服务端已经建立了连接)。
随后服务端初始化产生了随机序列号seq=y,并将SYN,ACK置为1,产生ack确认号x+1(收到的连接报文的序列号+1),向客户端发送包含这些信息的ack确认报文,告诉客户端自己已经收到了连接报文并且建立了连接。

第三次握手:

客户端收到服务端发来的ack确认报文(ACK=1),知道了服务端已经收到连接报文。从该确认报文中获得SYN=1知道服务端已经同意了这次连接并且客户端需要把服务端产生的序列号seq=y保存在客户端(此时客户端已经建立了连接)
客户端需要向客户端发送一个ack确认报文来告诉服务端自己已经建立了连接。这个确认报文包含ack标志位ACK=1,ack确认号y+1(第二次握手时服务端传来的序列号+1)以及序列号seq=x+1(这个+1是因为在第一次握手时客户端消耗了一个序列号)。

经过这三次握手之后,双方均建立了连接,可以开始收发数据了。

注意点:第三次握手是考虑到连接时丢包的问题。如果只握手2次,第二次握手时如果服务端发给客户端的确认报文段丢失,此时服务端已经准备好了收发数据,而客户端一直没收到服务端的确认报文,所以客户端就不知道服务端是否已经准备好了(可以理解为客户端未连接成功),这种情况下客户端不会给服务端发数据,也会忽略服务端发过来的数据。
如果是三次握手,即便发生丢包也不会有问题,比如如果第三次握手客户端发的确认ack报文丢失,服务端在一段时间内没有收到确认ack报文的话就会重新进行第二次握手,也就是服务端会重发SYN报文段,客户端收到重发的报文段后会再次给服务端发送确认ack报文。

四次挥手断开连接

四次挥手
比如客户端初始化的序列号ISN=x,服务端初始化的序列号ISN=y。TCP连接成功后客户端总共发送了1000个字节的数据,服务端在客户端发FIN报文前总共回复了2000个字节的数据。

第一次挥手:

客户端向服务端发送连接释放报文(FIN=1),告诉服务端自己要断开连接。(报文发出后客户端停止向服务端发送数据,但仍然可以接收数据)该报文携带了序列号seq=x+1+1000(+1为第一次握手时消耗的序列号)。

第二次挥手:

服务端收到客户端发来的连接释放报文(检测到FIN=1),随后服务端会向客户端发送ack确认报文(ACK=1,ack=x+1+1000+1,seq=y+2000)。
此时服务端处于关闭等待状态,而不是立马给客户端发FIN报文,这个状态还要持续一段时间,因为服务端可能还有数据没发完。

第三次挥手:

服务端向客户端发送完数据后(假设这里发送了100个字节的数据),服务端向客户端发送连接释放报文(FIN=1,ACK=1,ack=x+1+1000+1.seq=y+2000+100),告诉客户端服务端已经准备好关闭连接。

第四次挥手:

客户端收到来自服务端的连接释放报文(检测到FIN=1),知道了服务端已经做好关闭连接的准备,于是客户端向服务端发送ack确认报文(ACK=1,ack=y+2000+100+1,seq=x+1+1000+1,由于FIN报文段即使不携带数据也要占据一个序列号,所以这里的seq的第二个+1就是这样来的),通知服务端可以关闭连接了。

服务端收到连接释放报文后立即关闭连接,而客户端还要等待2MSL(最长报文段寿命的2倍时长)后才释放TCP连接。

等待2MSL是为了防止丢包,如果第四次挥手的报文丢失,服务端没收到确认ack报文就会重发第三次挥手的报文,这样报文一去一回最长时间就是2MSL,所以需要等这么长时间来确认服务端确实已经收到了。

TCP的特点及使用场景
特点:

传输效率相对较低,但是它能确保数据准确到达(对方没有收到就重发)

使用场景:

传输一个文件,就必须保证所有数据准确到达,如果发生丢包那这个文件数据就不完整了,所以就用TCP。再比如做即时通讯,我给你发送一条消息,那肯定是要保证你成功收到消息,所以这种一般也是用TCP。

文章参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值