12 tcp协议详解

1、tcp的本性

tcp是一个悲观者,生下来就不信任网络,任务会发生丢包等,所以要从算法层面来保证可靠性。

2、TCP 包头格式

tcp的包头格式比UDP要复杂的多。
在这里插入图片描述

1.源端口号和目标端口号是不可少的,这一点和 UDP 是一样的。如果没有这两个端口号。数据就不知道应该发给哪个应用。
2.包的序号:是为了解决乱序的问题。不编好号怎么确认包到达的前后顺序。
3.确认序号:发出去的包需要ack,不然我也不知道有没有收到,如果没有收到,就应该重发,直到收到为止。
  //这个可以解决不丢包的问题
4.状态位:
  SYN:是发起一个连接
  ACK 是回复
  RST 是重新连接
  FIN 是结束连接
  //TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更

注意:tcp虽然是靠谱的协议,但是网络环境不好的时候,对于IP层丢不丢包,它也没有办法,tcp唯一能做的就是不断地重试。

3、tcp的握手和技能
  1. tcp如何保证对于连接的信任呢,为什么需要握手呢,这就好比人与人之间不会第一次见面就信任对方吧,怎么也得握手几次吧。
  2. tcp做流量控制:通信双方各声明一个窗口,标识自己当前能够的处理能力,别发送的太快,也别发的太慢。
  3. tcp拥塞控制:对于网络是否拥堵,tcp是无能为力的,唯一能做的就是控制自己,也即控制发送的速度。
  4. tcp需要关注的点如下:
1.顺序问题 ,稳重不乱
2.丢包问题,承诺靠谱
3.连接维护,有始有终
4.流量控制,把握分寸
5.拥塞控制,知进知退
4、TCP 的三次握手

tcp连接的建立,又称3次握手,这是一个连接维护的问题,这样比较便于理解。
就是一个:“请求 -> 应答 -> 应答之应答

A: 您好,我是A
B: 您好,我是B
A:  您好,B

为啥不是2次,4次?

1.假设网络环境不好,A发出了一个请求,包有可能会丢失或者请求超时了,于是A一直补发,直到B收到了请求,但是B收到的请求的时候,A可能不直到,所以A还会再发。
  如果B收到了请求:
    一是B不愿意建立练级,A会在一定时间后放弃
    二是B愿意建立连接,像A发送一个ack,但是B发出去的包也会像石沉大海一样,也不知道A有没有收到。
另外还有一种可能,就是之前A发送包出去绕了一圈回来了,B接收到了,同样认为这是一个正常的请求,于是给出了响应,这事听起来也是挺离谱的。
so,2次握手是不可靠的!

2. 为啥不是4次?
不是4次不行,400次都行,只是这样会没完没了,理由如下:
B发出的消息可能会发送多次,A只要收到一次,就认为连接建立了,自己的请求有了响应,A发送一个应答的应答。
而B也在等这个消息,才能确认连接是否建立,只有等到了这个消息,对于B来说,这个消息是有始有终的。
对于应答的应答,也有可能会丢,会绕路,甚至B都宕机了,是不是需要B再这个基础之上再应答,如此的话,就是没完没了了。

只要双方的消息都有去有回,就基本可以了

1.大部分情况下,AB 建立了连接之后,A 会马上发送数据的,这个时候很多问题就得到了解决。
//例如 A 发给 B 的应答丢了,当 A 后续发送的数据到达的时候,B 可以认为这个连接已经建立,或者 B 压根就挂了,A 发送的数据,会报错,说 B 不可达,A 就知道 B 出事情了。
2.如果A 比较坏,就是不发数据,建立连接后空着。我们在程序设计的时候,可以要求开启keepalive 机制,即使没有真实的数据包,也有探活包。
3.我们作为服务的提供者来说,如果A一直不发包,则可以主动关闭这个连接
5、包的序号问题
  1. 三次握手除了双方建立连接外,主要还是为了沟通一件事情,就是TCP 包的序号的问题。
  2. 每个连接都要有不同的序号。这个序号的起始序号是随着时间变化的。
  3. 序号,可以看成一个 32 位的计数器,每 4ms 加一。
  4. IP 包头里面有个 TTL,也即生存时间。
6、TCP 四次挥手

在这里插入图片描述

7、tcp是咋靠谱的?
1.tcp为了保证顺序性,每一个包都有一个 ID
2.在建立连接的时候,会商定起始的 ID 是什么,然后按照 ID 一个个发送。
3.为了保证不丢包,对于发送的包都要进行应答。

累计确认/累计应答
应答也不是一个一个来的,而是会应答某个之前的 ID,表示都收到了,称为累计确认或者累计应答.

  1. 由上面可以猜到,这就必须得保存这些统计的结果。
  2. 为了记录所有发送的包和接收的包,TCP 也需要发送端接收端分别都有缓存来保存这些记录。
  3. 发送端的缓存里是按照包的 ID 一个个排列(队列),根据处理的情况分成四个部分,如下所示:
1.第一部分:发送了并且已经确认的
2.第二部分:发送了并且尚未确认的
3.没有发送,但是已经等待发送的
4.没有发送,并且暂时还不会发送的

为什么要区分第三部分和第四部分呢?
这就是之前提到的流量控制,如果对方的处理能力弱,就等等再发。

Advertised window:

  1. 在 TCP 里,接收端会给发送端报一个窗口的大小,称Advertised window
  2. 窗口的大小应该等于上面的 第二部分 + 第三部分
    就是已经发送的正在处理的部分,再加上等待发送的部分已经是接收端处理的上线了,再多,就吃不下了。

发送端的数据结构:
依照服务端的要求,发送端的数据结构如下:
在这里插入图片描述LastByteAcked:第一部分和第二部分的分界线
LastByteSent:第二部分和第三部分的分界线
LastByteAcked + AdvertisedWindow:第三部分和第四部分的分界线

对于接收端来讲,它的缓存里记录的内容相对简单
第一部分:接受并且确认过的
第二部分:还没接收,但是马上就能接收的,即当前最大的处理能力
第三部分:还没接收,也没法接收的,即超负荷了
在这里插入图片描述MaxRcvBuffer:最大缓存的量
LastByteRead 之后是已经接收了,但是还没被应用层读取的
NextByteExpected 是第一部分和第二部分的分界线

第二部分的窗口有多大呢?

1.NextByteExpected 和 LastByteRead 的差其实是还没被应用层读取的部分占用掉的 MaxRcvBuffer 的量,我们定义为 A
2.AdvertisedWindow 其实是 MaxRcvBuffer 减去 A,也就是:AdvertisedWindow=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead)
//那第二部分和第三部分的分界线在哪里呢?
1.NextByteExpected 加 AdvertisedWindow 就是第二部分和第三部分的分界线,其实也就是 LastByteRead 加上 MaxRcvBuffer.
2.第二部分里面,由于接收到的包可能不是顺序的,会出现空挡,只有和第一部分连续的,可以马上进行回复,中间空着的部分需要等待,哪怕后面的已经来了

顺序和丢包问题:涉及了RTT,自适应重传算法等,此处不做过多解读,感兴趣可以Google一下

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值