# 【NO.446】后端开发【一大波干货知识】tcp/ip定时器与滑动窗口详解

## 1.为什么udp有包长，而tcp没有包长。

首先，send()发送一次发送1k，发送一次缓冲区满了就会返回-1。2k发送出去后缓冲区被清空，send()才会被再次调用。最大传输片会打印四个包发送。而最大传输单元是在数据链路层对网卡的一些限制，如果mss大于mtu时候就会被分割，而mss小于mtu时候就会直接发送。所以udp需要包长，而tcp不需要因为mss+tcp包头就可以完成不需要包长。具体点说，就是帧需要，加上512，可以将包长进行计算出，这里不做重复的事减轻了很多后续工作。

- 发送1m的文件
- sendbuf 2k
- mss（最大传输片）=512，mss是在包头的option中设置的。
- mtu（最大传输单元）=1500

## 2.协议头分析

- ACK表示确认
- PSH表示应用程序发来数据赶紧处理呀宝贝
- RST表示告诉对端你的数据不合法，重置
- SYN表示同步头
- FIN表示古德拜啦~断开前兆

## 3.慢启动的问题

![img](https://linuxcpp.0voice.com/zb_users/upload/2022/12/13/20221213163738_92368.jpg)

对数增长慢启动后，线性增拥塞控制，最后是要快速重传。

进入弱网环境，rtt（数据包往返）出现很长时间，这就叫抖动。

rtt=0.1rtt(new)+0.9rtt(old)这是一个消抖的过程，通信专业知识，有时间应该去学学一下研究通信啦！得出的值就可以判断是否超时。当然了，拥塞避免增长速度肯定是没有慢启动指数增长的快，但是面积大，面积就是传输的数量，所以拥塞避免是为了保证传输的量更加大。

## 4.如果接收端缓冲区buffer满了，但是没有丢失数据，还会发吗？会

就不会发了呀宝贝。回应上写的windows为0。服务端的recvbuf和回应客户端返回的window完全是两个不同的概念，但是两个值会一直接近。

## 5.如果服务器端recvbuf从无到有，如何告诉客户端我有空间了呢？

服务器主动告诉客户端，我的recvbuf不为0

客户端轮询

第一种服务器主动告诉客户端，优点是实时性比较好，但是缺点是发生丢包怎么办？将会陷入死锁的状态。如果做一个定时器会不会好一点？可是客户端关机了怎么办？

**TCP的做法是什么呢？

当服务器recvbuf为0的时候，客户端主动轮训发送探测包，服务器的有空间吗？服务器被动的回。

**

如果服务器主动发送回复客户端，客户端不回服务器多次发送可以不？做法是可行的，但是违背了原则，毕竟服务器也不愿意当舔狗，主动向全世界客户端宣布爱你。

## 6.滑动窗口的运行机制

两个指针表示收尾，第三根指针作为成功接收否的标记指针，尾指针后面的接收的指针不处理。

![img](https://linuxcpp.0voice.com/zb_users/upload/2022/12/13/20221213163738_30203.jpg)

TCPkeepalive和应用层keepalive，应用层的keepalive可控性更强，而TCPkeepalive很笨，有点像小刘同学嘎嘎幸亏她不知道要不然肯定会打我，应用层你感知不到好难受。

## 7.问答环节

Q1：tcp利用send函数发送数据发现数据丢失了，需要在应用层对丢包重传处理吗？

答:利用tcp传输数据，发送数据是一定会发送到对端网卡。如果你发生丢包，那要注意send()返回值是为-1，应用层处理业务逻辑有问题。往往错误都是一些低端的错误。

Q2:滑动窗口的尾指针后面组织准备接受数据的状态，这是哪里在组织，操作系统吗？

答：是tcp协议组织的。

Q3：如图，当客户端有多个数据包同时发送给服务器，发送中途状态服务器的recvbuf满了，服务器需要立刻通知客户端吗？还是要等一个阶段的数据发送的差不多了再告诉客户端有一部分数据未接收成功？目前看来，这个状况是服务器性能问题，所以不会进入快速重传状态对吧？

答：要发送多少，是接收端返回数据。接收端接收数据数据以后，会回ack，ack里面就会确定，还能接受大小。

![img](https://linuxcpp.0voice.com/zb_users/upload/2022/12/13/20221213163739_22687.jpg)

原文链接：https://zhuanlan.zhihu.com/p/494470170

作者：[Hu先生的Linux](https://www.zhihu.com/people/huhu520-10)