⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生。
如果觉得本文能帮到您,麻烦点个赞
呗!
近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。⭐️❤️
Qt5.9专栏
定期更新Qt的一些项目Demo
项目与比赛专栏
定期更新比赛的一些心得,面试项目常被问到的知识点。
Linux Web Server
项目虽然是现在C++求职者的人手一个的项目,但是想要吃透这个项目,还是需要一定的基础的,以项目为导向,进行基础的学习。
涵盖了计算机网络(网络编程)
常见的知识点和常见的操作系统知识
。
博主参加过大大小小的互联网厂和银行的秋招和春招的笔试与面试,整理了下面的2万7千字的长文(都是干货,写作不易啊),喜欢,觉得有帮助的,欢迎订阅专栏,后续有很多优质的文章进行更新,有任何疑问,欢迎留言!
closed(关闭)
状态,服务器处于 listen(监听)
状态。SYN = 1
同步序列号和初始化序列号seq = x
发送给服务端,发送完之后客户端处于SYN_Send
状态。(验证了客户端的发送能力和服务端的接收能力)SYN
请求报文之后,如果同意连接,会以自己的同步序列号SYN(服务端) = 1
、初始化序列号 seq = y
和确认序列号(期望下次收到的数据包)ack = x+ 1
以及确认号ACK = 1
报文作为应答,服务器为SYN_Receive
状态。SYN + ACK
之后,知道可以下次可以发送了下一序列的数据包了,然后发送确认序列号 ack = y + 1
和数据包的序列号 seq = x + 1
以及确认号ACK = 1
确认包作为应答,客户端转为established
状态。(分别站在双方的角度上思考,各自ok)第三次握手主要为了防止已失效的连接请求报文段突然又传输到了服务端,导致产生问题。
FIN=1,seq=u
),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1
(终止等待1)状态,等待B的确认。ACK=1,ack=u+1,seq=v
),B进入CLOSE-WAIT
(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。FIN-WAIT-2
(终止等待2)状态,等待B发出的连接释放报文段。FIN=1,ACK=1,seq=w,ack=u+1
),B进入LAST-ACK
(最后确认)状态,等待A的确认。ACK=1,seq=u+1,ack=w+1
),A进入TIME-WAIT
(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL
(最大报文段生存时间)后,A才进入CLOSED
状态。B收到A发出的确认报文段后关闭连接,若没收到A发出的确认报文段,B就会重传连接释放报文段。因为当Server端收到Client端的SYN
连接请求报文后,可以直接发送SYN+ACK
报文。但是在关闭连接时,当Server端收到Client端发出的连接释放报文时,很可能并不会立即关闭SOCKET,所以Server端先回复一个ACK
报文,告诉Client端我收到你的连接释放报文了。只有等到Server端所有的报文都发送完了,这时Server端才能发送连接释放报文,之后两边才会真正的断开连接。故需要四次挥手。
ACK
报文段有可能丢失,B收不到这个确认报文,就会超时重传连接释放报文段,然后A可以在2MSL
时间内收到这个重传的连接释放报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到CLOSED
状态,若A在TIME-WAIT
状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的连接释放报文段,所以不会再发送一次确认报文段,B就无法正常进入到CLOSED
状态。ACK
报文段后,再经过2MSL,就可以使这个连接所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现旧的连接请求报文段。比如向我们现在这样通话,假设出现丢包的情况,应该如何处理
没有考虑过
参考答案:
UDP通信—收包率低/丢包率高的
原因:
(1)缓存太小,不能及时接收数据
连续多个UDP包超过了UDP缓冲区大小,比如
1、UDP包过大
2、UDP发包速率过快,突发大数据流量超过了缓冲区上限
(2)recvfrom()
接收到数据之后处理速度太慢
如果数据接收和处理是连续进行的,那么可能由于数据处理过慢,两次recvfrom()
调用的时间间隔发过来的包丢失
解决办法
解决办法:增加系统发送或接收缓冲区大小
int nBuf = 32 * 1024
setsockopt(s,SOL_SOCKET, SO_RCVBUF, (const char*)&nBuf, sizeof(int));
setsockopt(s,SOL_SOCKET, SO_SNDBUF, (const char*)&nBuf ,sizeof(int))
解决办法:增加一个应答机制,处理完一个包后,在继续发包
recvfrom()
接收到数据之后处理速度太慢
服务器程序启动之后,开辟两个线程,一个线程专门用于接受数据包,并存放在应用层的缓冲区;另外一个线程用于专门处理和相应数据包请求,避免因为处理数据造成数据丢失。本质上还是增大了缓冲区大小,只是将系统的缓冲区移动到了自己的缓冲区。
在应用层实现丢包重发机制和超时机制,确保数据包不丢失。
一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和粘包问题。
1、应用程序写入数据的字节大小大于套接字发送缓冲区的大小.
2、进行MSS大小的TCP分段。( MSS(网络传输最大值)=TCP报文段长度-TCP首部长度)
3、以太网的payload大于MTU进行IP分片。( MTU指:一种通信协议的某一层上面所能通过的最大数据包大小。)
1、消息定长。
2、在包尾部增加回车或者空格符等特殊字符进行分割
3、将消息分为消息头和消息尾。
4、使用其它复杂的协议,如RTMP(实时信息传输协议)协议等。
TCP粘包、拆包及解决办法
为什么常说 TCP 有粘包和拆包的问题而不说 UDP ?
由前两节可知,UDP 是基于报文发送的,UDP首部采用了 16bit 来指示 UDP 数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。
而 TCP 是基于字节流的,虽然应用层和 TCP 传输层之间的数据交互是大小不等的数据块,但是 TCP 并没有把这些数据块区分边界,仅仅是一连串没有结构的字节流;另外从 TCP 的帧结构也可以看出,在 TCP 的首部没有表示数据长度的字段,基于上面两点,在使用 TCP 传输数据时,才有粘包或者拆包现象发生的可能。
为什么会发生 TCP 粘包、拆包?
粘包、拆包解决办法
由于 TCP 本身是面向字节流的,无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,归纳如下:
计算机网络的部分图片:https://interviewguide.cn/
最后,最后
如果觉得有用,麻烦三连⭐️❤️支持一下呀,希望这篇文章可以帮到你,你的点赞是我持续更新的动力