面试官:用了 TCP 协议,肯定不会丢包

表面上我是个技术博主 。
但没想到今天成了个情感博主 。
我是没想到有一天,我会通过技术知识,来挽救粉丝即将破碎的感情 。
掏心窝子的说 。这件事情多少是沾点功德无量了 。
事情是这样的 。
最近就有个读者加了我的绿皮聊天软件,女生,头像挺好看的,就在我以为她要我拉她进群发成人专升本广告的时候 。
画风突然不对劲 。
她说她男朋友也是个程序员,异地恋,也关注了我,天天研究什么 TCP、UDP 网络 。一研究就是一晚上,一晚上都不回她消息的那种 。
话里有话,懂 。
不出意外的出了意外,她发出了灵魂拷问
"你们程序员真的有那么忙吗?忙到连消息都不知道回 。"
没想到上来就是一记直拳 。
但是,这一拳,我接住了 。
我很想告诉她 "分了吧,下一题" 。
但我不能 。因为这样我就伤害了我的读者兄弟 。
沉默了一下 。
单核 CPU 都快转冒烟了,才颤颤巍巍在九宫格键盘上发出消息 。
再回慢一点,我就感觉,我要对不起我这全日制本科学历了 。
"其实,他已经回了你消息了,但你知道吗?网络是会丢包的 。"
"我来帮他解释下,这个话题就要从数据包的发送流程聊起" 。
数据包的发送流程
首先,我们两个手机的绿皮聊天软件客户端,要通信,中间会通过它们家服务器 。大概长这样 。
【面试官:用了 TCP 协议,肯定不会丢包】聊天软件三端通信
但为了简化模型,我们把中间的服务器给省略掉,假设这是个端到端的通信 。且为了保证消息的可靠性,我们盲猜它们之间用的是 TCP 协议进行通信 。
聊天软件两端通信
为了发送数据包,两端首先会通过三次握手,建立 TCP 连接 。
一个数据包,从聊天框里发出,消息会从聊天软件所在的用户空间拷贝到内核空间的发送缓冲区(send ),数据包就这样顺着传输层、网络层,进入到数据链路层,在这里数据包会经过流控(qdisc),再通过发到物理层的网卡 。数据就这样顺着网卡发到了纷繁复杂的网络世界里 。这里头数据会经过 n 多个路由器和交换机之间的跳转,最后到达目的机器的网卡处 。
此时目的机器的网卡会通知 DMA 将数据包信息放到中,再触发一个硬中断给 CPU,CPU 触发软中断让去收包,于是一个数据包就这样顺着物理层,数据链路层,网络层,传输层,最后从内核空间拷贝到用户空间里的聊天软件里 。
网络发包收包全景图
画了那么大一张图,只水了 200 字做解释,我多少是有些心痛的 。
到这里,抛开一些细节,大家大概知道了一个数据包从发送到接收的宏观过程 。
可以看到,这上面全是密密麻麻的名词 。
整条链路下来,有不少地方可能会发生丢包 。
但为了不让大家保持蹲姿太久影响身体健康,我这边只重点讲下几个常见容易发生丢包的场景 。
建立连接时丢包
TCP 协议会通过三次握手建立连接 。大概长下面这样 。
TCP 三次握手
在服务端,第一次握手之后,会先建立个半连接,然后再发出第二次握手 。这时候需要有个地方可以暂存这些半连接 。这个地方就叫半连接队列 。
如果之后第三次握手来了,半连接就会升级为全连接,然后暂存到另外一个叫全连接队列的地方,坐等程序执行() 方法将其取走使用 。
半连接队列和全连接队列
是队列就有长度,有长度就有可能会满,如果它们满了,那新来的包就会被丢弃 。
可以通过下面的方式查看是否存在这种丢包行为 。