网络协议
经典协议与数据包
以太网首部,包含主机mac地址等信息
TCP的三次握手和四次挥手
为什么需要3次握手?
主要目的是保证连接是双工和可靠的,可靠更多是通过重传机制来保证的。
双工是指发送和接受是可以同时执行的。
为什么需要四次挥手?
因为连接是全双工的,双方必须都收到对方的FIN包及确认才可关闭。
为什么最大等待时间是2MSL?
MSL : Maximum Segment Lifetime, 30s~1分钟。最大的段的生命周期。
- 保证TCP协议的全双工连接能够可靠关闭。
若主动关闭放发送最后一个ack包不等到2MSL的话:若这个ack包丢失了,主动发送放可以通过失败重传机制,再次 发送FIN包给主动关闭方,若没有2MSL,可能就收不到这个包,同时主动关闭方关闭了通道,那么被动关闭方就会一直 处于LAST-ACK状态,资源得不到释放。
- 保证这次连接的重复数据段从网络中消失
若不等待的话,当关闭了这次会话过后,又建立了连接,恰好是同样的服务器,同样的端口。若不等待2MSL,在前一次最后一次 的请求接受失败,就会重传,那么新建立的连接就会收到不正确的消息。
为啥会出现大量的close_wait?
- 首先,close_wait一般出现在被动关闭方
- 并发请求太多导致
- 被动关闭方未及时释放端口资源导致
TCP为啥需要流量控制?UDP不需要? UDP是不可靠的连接,发送了就不管了,不需要控制
TCP需要流量控制的原因:
- 由于通讯双方,网速不同。通讯方任一发送过快都会导致对方消息处理不过来,所以就需要把数据 放到缓冲区中
- 如果缓冲区满了,发送方还在疯狂发送,那接收方只能把数据包丢弃。因此我们需要控制发送速率
- 缓冲区剩余大小称之为接受窗口,用变量win表示,如果win=0,则发送方停止发送。
TCP为啥需要用塞控制?
拥塞控制和流量控制是两个概念,拥塞控制是调整网络负载 产生的原因: 接收方网络资源繁忙,因未及时响应ACK导致发送方重传大量数据,这样将会导致网络 更加拥堵。 解决:拥塞控制动态调整win大小,不只是依赖缓冲区确定窗口大小,主要分为两个部分
- 慢开始
刚刚建立的时候一点点的提速,试探网络的速度。
- 拥塞避免
初始的时候慢启动开始,每次传输过后,逐渐递增至特定阀值。然后采用拥塞避免方式加法增加传输。当发生网络拥塞的时候, 直接传输从最小开始,然后,再次指数增长,特定阀值变化为上次发生拥塞的值的一般,到达此值的时候再次加法增加,重复此动作。
这样有个缺点,从最高值直接降低为1会对传输有很大的影响,所以,有了下一种优化算法
不同点再发生网络拥塞的时候,不会直接变为1,而是从一半开始,加法增加
什么是粘包/拆包?为什么会发生?
产生粘包和拆包问题的主要原因是,操作系统在发送TCP数据的时候,底层会有一个缓冲区,例如1024个字节大小,如果一次请求发送的数据量比较小, 没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,这就形成了粘包问题;如果一次请求发送的数据量比较大,超过了缓冲区大小, TCP就会将其拆分为多次发送,这就是拆包,也就是将一个大的包拆分为多个小包进行发送。 TCP 是一个面向字节流的协议,它是性质是流式的,所以它并没有分段。就像水流一样,你没法知道什么时候开始,什么时候结束。 粘包问题是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
- 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包
- 应用程序写入的数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将发生粘包
- 进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包
- 接受方法不及时读取套接字缓冲区数据,这将发生粘包
如何获取完整的数据报文?
- 使用带消息头的协议,头部写入包长度,然后再读取包内容
- 设置定长消息,每次读取定长内容,长度不够时空位补固定字符
- 设置消息边界,服务端从网络流中按消息边界分离出消息内容,一般使用 “ \n “
- 使用更为复杂的协议,如:json、protobuf等