潮州哪里做网站,网站修改字体尺寸怎么做,深圳网站建设公司信任湖南岚鸿信 赖,app开发公司组织结构图目录
1. 流量控制
2. 滑动窗口
3. 拥塞控制
4. 延迟应答
5. 捎带应答
6. 面向字节流
7. 粘包问题
8. TCP异常情况 1. 流量控制 接收端处理数据的速度是有限的. 如果发送端发的太快 , 导致接收端的缓冲区被打满 , 这个时候如果发送端继续发送 , 就会造成丢包, 继而引…目录
1. 流量控制
2. 滑动窗口
3. 拥塞控制
4. 延迟应答
5. 捎带应答
6. 面向字节流
7. 粘包问题
8. TCP异常情况 1. 流量控制 接收端处理数据的速度是有限的. 如果发送端发的太快 , 导致接收端的缓冲区被打满 , 这个时候如果发送端继续发送 , 就会造成丢包, 继而引起丢包重传等等一系列连锁反应 . 因此TCP 支持根据接收端的处理能力 , 来决定发送端的发送速度 . 这个机制就叫做 流量控制 (Flow Control) ; 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 窗口大小 字段, 通过ACK端通知发送端; 窗口大小字段越大, 说明网络的吞吐量越高; 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端; 发送端接受到这个窗口之后, 就会减慢自己的发送速度; 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端。第一次发送数据时的窗口大小是在三次握手时交换的。 2. 滑动窗口 在上一篇文章中介绍了ACK确认应答和超时重传机制那么根据前面已有的知识如果发送数据在没有收到应答之前必须将已经发送的数据暂时保留用来在没有收到确认ACK时实现超时重传机制会保存在滑动窗口中。若是收到ACK后再发送下一个数据段这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候 为了使得传输效率变得更高可以有下图中的传输策略 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是4000个字节(四个段). 发送前四个段的时候, 不需要等待任何ACK, 直接发送 收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推; 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉; 窗口越大, 则网络的吞吐率就越高; 滑动窗口左侧是已发送并已收到ACK的数据窗口中的数据未已发送未收到ACK的数据右侧为未发送数据或无数据。 发送端滑动窗口的初始大小是基于发送方的配置和标准确定的在发送数据的过程中根据对方接收缓冲区的大小动态的调整。窗口滑动示意如下 不过窗口不是一定会向右滑动的
窗口保持不变发送的数据速度与接收到ACK的速度相当时窗口变小对方接收缓冲区满了窗口end端不在变化且一直收到对方的ACKstart端不断靠近end端窗口变大由于网络拥堵等的情况一直未收到对方的ACKstart端不变化或者速度较慢而对方接受缓冲区在变大一直发送新的数据窗口end端一直向右移动。
若发生丢包情况怎么办呢
情况一数据没丢只是应答丢了 -- 这种情况是无需担心的因为可以通过后续的ACK进行确认。发送端在收到下一个应答的序号为ack_seq x1表示x1之前的数据已经全部收到了如下图所示 情况二数据包真的丢失了 当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 我想要的是 1001一样; 如果发送端主机连续三次收到了同样一个 1001 这样的应答, 就会将对应的数据 1001 - 2000 重新发送; 这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中
这种机制叫做“高速重发控制”(快重传)比超时重发机制要快。
3. 拥塞控制 虽然TCP 有了滑动窗口这个大杀器 , 能够高效可靠的发送大量的数据 . 但是如果在刚开始阶段就发送大量的数据 , 仍然可能引发问题. 因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵 . 在不清楚当前网络状态下 , 贸然发送大量的数据 , 是很有可能引起雪上加霜的. TCP引入 慢启动 机制 , 先发少量的数据 , 探探路 , 摸清当前的网络拥堵状态 , 再决定按照多大的速度传输数据 此处引入一个概念程为拥塞窗口 发送开始的时候, 定义拥塞窗口大小为1; 每次收到一个ACK应答, 拥塞窗口加1; 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;
慢启动只是启动的时候慢但是是指数级的增长速度。为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍。此处引入一个叫做慢启动的阈值当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长。如下图所示 4. 延迟应答 如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K; 但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了; 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来; 如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M; 并不是所有的包都要延迟应答
数量限制: 每隔N个包就应答一次; N一般为2时间限制: 超过最大延迟时间就应答一次 超时时间取200ms 延迟应答不仅可以返回简答的窗口大小 还可以
合并ACK如果连续收到两个TCP包并不一定需要ACK两次只要回复最终的ACK就可以了可以降低网络流量。如果接收方有数据要发送那么就会在发送数据的TCP数据包里带上ACK信息。这样做可以避免大量的ACK以一个单独的TCP包发送减少了网络流量
5. 捎带应答 在延迟应答的基础上 , 我们发现 , 很多情况下 , 客户端服务器在应用层也是 一发一收 的 . 意味着客户端给服务器说了 How are you, 服务器也会给客户端回一个 Fine, thank you; 那么这个时候 ACK 就可以搭顺风车 , 和服务器回应的 Fine, thank you 一起回给客户端 6. 面向字节流 当用户消息通过 TCP 协议传输时消息可能会被操作系统分组成多个的 TCP 报文也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。
创建一个TCP的socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区; 调用write时, 数据会先写入发送缓冲区中; 如果发送的字节数太长, 会被拆分成多个TCP的数据包发出; 如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或者其他合适的时机发送出去; 接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区; 然后应用程序可以调用read从接收缓冲区拿数据; 另一方面, TCP的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一个连接, 既可以读数据, 也可以写数据. 这个概念叫做 全双工 由于缓冲区的存在, TCP程序的读和写不需要一一匹配, 例如: 写100个字节数据时, 可以调用一次write写100个字节, 也可以调用100次write, 每次写一个字节; 读100个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100个字节, 也可以一次read一个字节, 重复100次; 7. 粘包问题
如果一次请求发送的数据量比较小没达到缓冲区大小TCP则会将多个请求合并为同一个请求进行发送这就形成了粘包问题 如果一次请求发送的数据量比较大超过了缓冲区大小TCP就会将其拆分为多次发送这就是拆包也就是将一个大的包拆分为多个小包进行发送。 那么如何避免粘包问题呢? 归根结底就是一句话, 明确两个包之间的边界
对于定长的包, 保证每次都按固定大小读取即可; 例如上面的Request结构, 是固定大小的, 那么就从缓冲区从头开始按sizeof(Request)依次读取即可; 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置; 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只要保证分隔符不和正文冲突即可) 对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交付给应用层. 就有很明确的数据边界. 站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会出现半个的情况。UDP是不存在粘包拆包问题的。 8. TCP异常情况
进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别. 机器重启: 和进程终止的情况相同. 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放. 另外 , 应用层的某些协议 , 也有一些这样的检测机制 . 例如 HTTP 长连接中 , 也会定期检测对方的状态 . 例如 QQ, 在 QQ线之后, 也会定期尝试重新连接 . 详细的可以参考这篇文章TCP 异常断开连接分析_tcp断连问题剖析-CSDN博客