您当前的位置:首页 > 电脑百科 > 网络技术 > 网络知识

用了TCP协议,就一定不会丢包吗?

时间:2022-08-03 10:41:20  来源:  作者:二哥学Java
表面上我是个技术博主。
但没想到今天成了个情感博主。
我是没想到有一天,我会通过技术知识,来挽救粉丝即将破碎的感情。
掏心窝子的说。这件事情多少是沾点功德无量了。
事情是这样的。
最近就有个读者加了我的绿皮聊天软件,女生,头像挺好看的,就在我以为她要我拉她进群发成人专升本广告的时候。
画风突然不对劲。
她说她男朋友也是个程序员,异地恋,也关注了我,天天研究什么TCP,UDP网络。一研究就是一晚上,一晚上都不回她消息的那种。
话里有话,懂。
不出意外的出了意外,她发出了灵魂拷问
"你们程序员真的有那么忙吗?忙到连消息都不知道回。"
没想到上来就是一记直拳。
但是,这一拳,我接住了。
我很想告诉她"分了吧,下一题"。
但我不能。因为这样我就伤害了我的读者兄弟。
沉默了一下。
单核cpu都快转冒烟了,才颤颤巍巍在九宫格键盘上发出消息。
再回慢一点,我就感觉,我要对不起我这全日制本科学历了。
"其实,他已经回了你消息了,但你知道吗?网络是会丢包的。"
"我来帮他解释下,这个话题就要从数据包的发送流程聊起"
数据包的发送流程
首先,我们两个手机的绿皮聊天软件客户端,要通信,中间会通过它们家服务器。大概长这样。
聊天软件三端通信
但为了简化模型,我们把中间的服务器给省略掉,假设这是个端到端的通信。且为了保证消息的可靠性,我们盲猜它们之间用的是TCP协议进行通信。
聊天软件两端通信
为了发送数据包,两端首先会通过三次握手,建立TCP连接。
一个数据包,从聊天框里发出,消息会从聊天软件所在的用户空间拷贝到内核空间的发送缓冲区(send buffer),数据包就这样顺着传输层、网络层,进入到数据链路层,在这里数据包会经过流控(qdisc),再通过RingBuffer发到物理层的网卡。数据就这样顺着网卡发到了纷繁复杂的网络世界里。这里头数据会经过n多个路由器和交换机之间的跳转,最后到达目的机器的网卡处。
此时目的机器的网卡会通知DMA将数据包信息放到中,再触发一个硬中断给,触发软中断让去收包,于是一个数据包就这样顺着物理层,数据链路层,网络层,传输层,最后从内核空间拷贝到用户空间里的聊天软件里。
图片
网络发包收包全景图
画了那么大一张图,只水了200字做解释,我多少是有些心痛的。
到这里,抛开一些细节,大家大概知道了一个数据包从发送到接收的宏观过程。
可以看到,这上面全是密密麻麻的名词。
整条链路下来,有不少地方可能会发生丢包。
但为了不让大家保持蹲姿太久影响身体健康,我这边只重点讲下几个常见容易发生丢包的场景。
建立连接时丢包
TCP协议会通过三次握手建立连接。大概长下面这样。
图片
TCP三次握手
在服务端,第一次握手之后,会先建立个半连接,然后再发出第二次握手。这时候需要有个地方可以暂存这些半连接。这个地方就叫半连接队列。
如果之后第三次握手来了,半连接就会升级为全连接,然后暂存到另外一个叫全连接队列的地方,坐等程序执行方法将其取走使用。
图片
半连接队列和全连接队列
是队列就有长度,有长度就有可能会满,如果它们满了,那新来的包就会被丢弃。
可以通过下面的方式查看是否存在这种丢包行为。
从现象来看就是连接建立失败。
图片
这个话题在之前写的《没有accept,能建立TCP连接吗?》有更详细的聊过,感兴趣的可以回去看下。
流量控制丢包
应用层能发网络数据包的软件有那么多,如果所有数据不加控制一股脑冲入到网卡,网卡会吃不消,那怎么办?让数据按一定的规则排个队依次处理,也就是所谓的qdisc(QueueingDisciplines,排队规则),这也是我们常说的流量控制机制。
排队,得先有个队列,而队列有个长度。
我们可以通过下面的命令查看到,里面涉及到的后面的数字,其实就是流控队列的长度。
当发送数据过快,流控队列长度又不够大时,就容易出现丢包现象。
图片
qdisc丢包
可以通过下面的命令,查看TX下的dropped字段,当它大于0时,则有可能是发生了流控丢包。
当遇到这种情况时,我们可以尝试修改下流控队列的长度。比如像下面这样将eth0网卡的流控队列长度从1000提升为1500.
网卡丢包
网卡和它的驱动导致丢包的场景也比较常见,原因很多,比如网线质量差,接触不良。除此之外,我们来聊几个常见的场景。
RingBuffer过小导致丢包
上面提到,在接收数据时,会将数据暂存到接收缓冲区中,然后等着内核触发软中断慢慢收走。如果这个缓冲区过小,而这时候发送的数据又过快,就有可能发生溢出,此时也会产生丢包。
图片
RingBuffer满了导致丢包
我们可以通过下面的命令去查看是否发生过这样的事情。
查看上面的指标,它记录了由于长度不足导致的溢出次数。
当然,用命令也能查看。
但这里需要注意的是,因为一个网卡里是可以有多个RingBuffer的,所以上面的里的0代表的是第0个RingBuffer的丢包数,对于多队列的网卡,这个0还可以改成其他数字。但我的家庭条件不允许我看其他队列的丢包数,所以上面的命令对我来说是够用了。。。
当发现有这类型丢包的时候,可以通过下面的命令查看当前网卡的配置。
上面的输出内容,含义是RingBuffer最大支持4096的长度,但现在实际只用了1024。
想要修改这个长度可以执行将发送和接收RingBuffer的长度都改为4096。
RingBuffer增大之后,可以减少因为容量小而导致的丢包情况。
网卡性能不足
网卡作为硬件,传输速度是有上限的。当网络传输速度过大,达到网卡上限时,就会发生丢包。这种情况一般常见于压测场景。
我们可以通过加网卡名,获得当前网卡支持的最大速度。
可以看到,我这边用的网卡能支持的最大传输速度speed=1000Mb/s。
也就是俗称的千兆网卡,但注意这里的单位是Mb,这里的b是指bit,而不是Byte。1Byte=8bit。所以10000Mb/s还要除以8,也就是理论上网卡最大传输速度是。
我们可以通过从网络接口层面来分析数据包的收发情况。
其中txkB/s是指当前每秒发送的字节(byte)总数,rxkB/s是指每秒接收的字节(byte)总数。
当两者加起来的值约等于的时候,也就对应大概的传输速度。此时达到网卡性能极限,就会开始丢包。
遇到这个问题,优先看下你的服务是不是真有这么大的真实流量,如果是的话可以考虑下拆分服务,或者就忍痛充钱升级下配置吧。
接收缓冲区丢包
我们一般使用进行网络编程的时候,内核都会分配一个发送缓冲区和一个接收缓冲区。
当我们想要发一个数据包,会在代码里执行,这时候数据包并不是一把梭直接就走网卡飞出去的。而是将数据拷贝到内核发送缓冲区就完事返回了,至于什么时候发数据,发多少数据,这个后续由内核自己做决定。之前写过的《代码执行send成功后,数据就发出去了吗?》里有比较详细的介绍。
图片
tcp_sendmsg逻辑
而接收缓冲区作用也类似,从外部网络收到的数据包就暂存在这个地方,然后坐等用户空间的应用程序将数据包取走。
这两个缓冲区是有大小限制的,可以通过下面的命令去查看。
不管是接收缓冲区还是发送缓冲区,都能看到三个数值,分别对应缓冲区的最小值,默认值和最大值 (min、default、max)。缓冲区会在min和max之间动态调整。
那么问题来了,如果缓冲区设置过小会怎么样?
对于发送缓冲区,执行send的时候,如果是阻塞调用,那就会等,等到缓冲区有空位可以发数据。
图片
send阻塞
如果是非阻塞调用,就会立刻返回一个 错误信息,意思是 。让应用程序下次再重试。这种情况下一般不会发生丢包。
图片
send非阻塞
当接受缓冲区满了,事情就不一样了,它的TCP接收窗口会变为0,也就是所谓的零窗口,并且会通过数据包里的,告诉发送端,"球球了,顶不住了,别发了"。一般这种情况下,发送端就该停止发消息了,但如果这时候确实还有数据发来,就会发生丢包。
图片
recv_buffer丢包
我们可以通过下面的命令里的查看到有没有发生过这种丢包现象。
但是说个伤心的事情,我们一般也看不到这个,因为这个是里引入的打点,而我们的服务器用的一般是左右版本。你可以通过下面的命令查看下你用的是什么版本的linux内核。
两端之间的网络丢包
前面提到的是两端机器内部的网络丢包,除此之外,两端之间那么长的一条链路都属于外部网络,这中间有各种路由器和交换机还有光缆啥的,丢包也是很经常发生的。
这些丢包行为发生在中间链路的某些个机器上,我们当然是没权限去登录这些机器。但我们可以通过一些命令观察整个链路的连通情况。
ping命令查看丢包
比如我们知道目的地的域名是 。想知道你的机器到bAIdu服务器之间,有没有产生丢包行为。可以使用ping命令。
ping查看丢包
倒数第二行里有个,意思是丢包率100%。
但这样其实你只能知道你的机器和目的机器之间有没有丢包。
那如果你想知道你和目的机器之间的这条链路,哪个节点丢包了,有没有办法呢?
有。
mtr命令
mtr命令可以查看到你的机器和目的机器之间的每个节点的丢包情况。
像下面这样执行命令。
图片
mtr_icmp
其中-r是指report,以报告的形式打印结果。
可以看到那一列,出现的都是链路中间每一跳的机器,的那一列就是指这一跳对应的丢包率。
需要注意的是,中间有一些是host是,那个是因为mtr默认用的是ICMP包,有些节点限制了ICMP包,导致不能正常展示。
我们可以在mtr命令里加个,也就是使用udp包,就能看到部分???对应的IP。
图片
mtr-udp
把ICMP包和UDP包的结果拼在一起看,就是比较完整的链路图了。
还有个小细节,那一列,我们在icmp的场景下,关注最后一行,如果是0%,那不管前面loss是100%还是80%都无所谓,那些都是节点限制导致的虚报。
但如果最后一行是20%,再往前几行都是20%左右,那说明丢包就是从最接近的那一行开始产生的,长时间是这样,那很可能这一跳出了点问题。如果是公司内网的话,你可以带着这条线索去找对应的网络同事。如果是外网的话,那耐心点等等吧,别人家的开发会比你更着急。
图片
发生丢包了怎么办
说了这么多。只是想告诉大家,丢包是很常见的,几乎不可避免的一件事情。
但问题来了,发生丢包了怎么办?
这个好办,用TCP协议去做传输。
图片
TCP是什么
建立了TCP连接的两端,发送端在发出数据后会等待接收端回复,的目的是为了告诉对方自己确实收到了数据,但如果中间链路发生了丢包,那发送端会迟迟收不到确认ack,于是就会进行重传。以此来保证每个数据包都确确实实到达了接收端。
假设现在网断了,我们还用聊天软件发消息,聊天软件会使用TCP不断尝试重传数据,如果重传期间网络恢复了,那数据就能正常发过去。但如果多次重试直到超时都还是失败,这时候你将收获一个红色感叹号。
图片
这时候问题又来了。
假设某绿皮聊天软件用的就是TCP协议。
那文章开头提到的女生,她男朋友回她的消息时为什么还会丢包?毕竟丢包了会重试,重试失败了还会出现红色感叹号。
于是乎,问题就变成了,用了TCP协议,就一定不会丢包吗?
用了TCP协议就一定不会丢包吗
我们知道TCP位于传输层,在它的上面还有各种应用层协议,比如常见的HTTP或者各类RPC协议。
图片
四层网络协议
TCP保证的可靠性,是传输层的可靠性。也就是说,TCP只保证数据从A机器的传输层可靠地发到B机器的传输层。
至于数据到了接收端的传输层之后,能不能保证到应用层,TCP并不管。
假设现在,我们输入一条消息,从聊天框发出,走到传输层TCP协议的发送缓冲区,不管中间有没有丢包,最后通过重传都保证发到了对方的传输层TCP接收缓冲区,此时接收端回复了一个,发送端收到这个后就会将自己发送缓冲区里的消息给扔掉。到这里TCP的任务就结束了。
TCP任务是结束了,但聊天软件的任务没结束。
聊天软件还需要将数据从TCP的接收缓冲区里读出来,如果在读出来这一刻,手机由于内存不足或其他各种原因,导致软件崩溃闪退了。
发送端以为自己发的消息已经发给对方了,但接收端却并没有收到这条消息。
于是乎,消息就丢了。
图片
使用TCP协议却发生丢包
虽然概率很小,但它就是发生了。
合情合理,逻辑自洽。
所以从这里,我铿锵有力的得出结论,我的读者已经回了这位女生消息了,只是因为发生了丢包所以女生才没能收到,而丢包的原因是女生的手机聊天软件在接收消息的那一刻发生了闪退。
到这里。女生知道自己错怪她男朋友了,哭着表示,一定要让她男朋友给她买一台不闪退的最新款iphone
额。。。
兄弟们觉得我做得对的,请在评论区扣个"正能量"。
这类丢包问题怎么解决?
故事到这里也到尾声了,感动之余,我们来聊点掏心窝子的话。
其实前面说的都对,没有一句是假话。
但某绿皮聊天软件这么成熟,怎么可能没考虑过这一点呢。
大家应该还记得我们文章开头提到过,为了简单,就将服务器那一方给省略了,从三端通信变成了两端通信,所以才有了这个丢包问题。
现在我们重新将服务器加回来。
聊天软件三端通信
大家有没有发现,有时候我们在手机里聊了一大堆内容,然后登录电脑版,它能将最近的聊天记录都同步到电脑版上。也就是说服务器可能记录了我们最近发过什么数据,假设每条消息都有个id,服务器和聊天软件每次都拿最新消息的id进行对比,就能知道两端消息是否一致,就像对账一样。
对于发送方,只要定时跟服务端的内容对账一下,就知道哪条消息没发送成功,直接重发就好了。
如果接收方的聊天软件崩溃了,重启后跟服务器稍微通信一下就知道少了哪条数据,同步上来就是了,所以也不存在上面提到的丢包情况。
可以看出,TCP只保证传输层的消息可靠性,并不保证应用层的消息可靠性。如果我们还想保证应用层的消息可靠性,就需要应用层自己去实现逻辑做保证。
那么问题叒来了,两端通信的时候也能对账,为什么还要引入第三端服务器?
主要有三个原因。
第一,如果是两端通信,你聊天软件里有好友,你就得建立连接。但如果引入服务端,你只需要跟服务器建立连接就够了,聊天软件消耗的资源越少,手机就越省电。
第二,就是安全问题,如果还是两端通信,随便一个人找你对账一下,你就把聊天记录给同步过去了,这并不合适吧。如果对方别有用心,信息就泄露了。引入第三方服务端就可以很方便的做各种鉴权校验。
第三,是软件版本问题。软件装到用户手机之后,软件更不更新就是由用户说了算了。如果还是两端通信,且两端的软件版本跨度太大,很容易产生各种兼容性问题,但引入第三端服务器,就可以强制部分过低版本升级,否则不能使用软件。但对于大部分兼容性问题,给服务端加兼容逻辑就好了,不需要强制用户更新软件。
所以看到这里大家应该明白了,我把服务端去掉,并不单纯是为了简单。
总结
数据从发送端到接收端,链路很长,任何一个地方都可能发生丢包,几乎可以说丢包不可避免。
平时没事也不用关注丢包,大部分时候TCP的重传机制保证了消息可靠性。
当你发现服务异常的时候,比如接口延时很高,总是失败的时候,可以用ping或者mtr命令看下是不是中间链路发生了丢包。
TCP只保证传输层的消息可靠性,并不保证应用层的消息可靠性。如果我们还想保证应用层的消息可靠性,就需要应用层自己去实现逻辑做保证。
最后给大家留个问题吧,mtr命令是怎么知道每一跳的IP地址的?
end


Tags:TCP协议   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
从零开始学习Python网络编程:探索TCP协议与实例演示!
Python 是一种高级的编程语言,拥有广泛的网络编程库。这些库允许 Python 开发者能够使用 TCP 和其他网络协议进行通信。在本文中,我们将探讨 TCP 协议,并通过一个简单的例子来...【详细内容】
2023-11-23  Search: TCP协议  点击:(220)  评论:(0)  加入收藏
Wireshark抓包分析TCP协议:三次握手和四次挥手
前言 面试中我们经常会被问到TCP协议的三次握手和四次挥手的过程,为什么总喜欢问这个问题呢? 其实我们平时使用的很多协议都是应用层协议,比如HTTP协议,https协议,DNS协议,FTP协议...【详细内容】
2023-11-01  Search: TCP协议  点击:(244)  评论:(0)  加入收藏
用了TCP协议,就一定不会丢包吗?
表面上我是个技术博主。但没想到今天成了个情感博主。我是没想到有一天,我会通过技术知识,来挽救粉丝即将破碎的感情。掏心窝子的说。这件事情多少是沾点功德无量了。事情是这...【详细内容】
2022-08-03  Search: TCP协议  点击:(338)  评论:(0)  加入收藏
手把手教你在netty中使用TCP协议请求DNS服务器
简介DNS的全称domain name system,既然是一个系统就有客户端和服务器之分。一般情况来说我们并不需要感知这个DNS客户端的存在,因为我们在浏览器访问某个域名的时候,浏览器作为...【详细内容】
2022-07-20  Search: TCP协议  点击:(448)  评论:(0)  加入收藏
从TCP协议的原理来谈谈rst复位攻击
在谈RST攻击前,必须先了解TCP:如何通过三次握手建立TCP连接、四次握手怎样把全双工的连接关闭掉、滑动窗口是怎么传输数据的、TCP的flag标志位里RST在哪些情况下出现。下面我...【详细内容】
2020-11-10  Search: TCP协议  点击:(392)  评论:(0)  加入收藏
从一个HTTP请求来读懂HTTP、TCP协议
作者公众号:org_yijiaoqian从一个HTTP请求来看网络分层原理 两台主机间会通过非常多网络设备,不管哪个网络设备都会发生数据丢失,如果发生数据丢失的话,会发生数据重传,会出现数...【详细内容】
2020-10-20  Search: TCP协议  点击:(170)  评论:(0)  加入收藏
工程师进阶:深入TCP协议
可能很多人对TCP协议都不陌生,网上也有很多资料关于TCP协议的讲解说明,但大多都比较片面,不能很全面的说明它的来龙去脉。小编也是整理了很久,找了很多资料,加上自己的理解写出了...【详细内容】
2020-08-10  Search: TCP协议  点击:(253)  评论:(0)  加入收藏
为何视频流/网游大都使用UDP协议,而不用TCP协议?
TCP协议协议特点:面向连接的可靠传输,报头20字节,存在流量控制机制(超时重发,丢弃重复数据,检验数据,分段排序,拥塞处理,滑动窗口机制,保证数据能从一端传到另一端。) TCP要保证丢失的p...【详细内容】
2020-06-01  Search: TCP协议  点击:(1895)  评论:(0)  加入收藏
DNS何时使用TCP协议,何时使用UDP协议?
DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类。但很少有人知道DNS分别在什么情况下使用这两种协议。TCP与UDPTCP:...【详细内容】
2019-12-19  Search: TCP协议  点击:(580)  评论:(0)  加入收藏
TCP协议与流通信
TCP(Transportation Control Protocol)协议与IP协议是一同产生的。事实上,两者最初是一个协议,后来才被分拆成网络层的IP和传输层的TCP。我们已经在UDP协议中介绍过,UDP协议是...【详细内容】
2019-11-11  Search: TCP协议  点击:(545)  评论:(0)  加入收藏
▌简易百科推荐
学生偷看“不良网站”,手机上3个痕迹无法清除,网友:咋不早说
众所周知,中国的常规教育中,总是“谈性色变”,但在这个信息爆炸的互联网时代,即便是一些年纪很小的孩子,也能轻易接触到一些所谓的不良网站,因此这一方面的教育缺失,其实是很可怕的...【详细内容】
2024-03-28    叶姐生活指南  Tags:不良网站   点击:(19)  评论:(0)  加入收藏
什么是网络中的路由器?核心功能解释
路由器是互联网连接的核心元素,是一种允许多个设备连接到互联网,并促进将数据包转发到各自的目标地址的设备。使用动态路由技术,路由器检查数据并在各种可用路径中选择最有效的...【详细内容】
2024-03-07    千家网  Tags:路由器   点击:(36)  评论:(0)  加入收藏
过年该不该升级Wi-Fi 7路由?看完就知道
打开电商网站不难发现,从2023年第三季度到现在,Wi-Fi 7路由器新品越来越多。而且价格不再是高高在上,已经基本和Wi-Fi 6路由价格差不多了。看到这些Wi-Fi 7新品路由,不少朋友就...【详细内容】
2024-02-27    中关村在线  Tags:Wi-Fi   点击:(45)  评论:(0)  加入收藏
聊聊 Kubernetes 网络模型综合指南
这篇详细的博文探讨了 Kubernetes 网络的复杂性,提供了关于如何在容器化环境中确保高效和安全通信的见解。译自Navigating the Network: A Comprehensive Guide to Kubernete...【详细内容】
2024-02-19  云云众生s  微信公众号  Tags:Kubernetes   点击:(43)  评论:(0)  加入收藏
SSL协议是什么?关于SSL和TLS的常见问题解答
SSL(安全套接字层)及其后继者TLS(传输层安全)是用于在联网计算机之间建立经过身份验证和加密的链接的协议。尽管SSL协议在 1999年已经随着TLS 1.0的发布而被弃用,但我们仍将这些...【详细内容】
2024-02-06  IDC点评网    Tags:SSL协议   点击:(74)  评论:(0)  加入收藏
从零开始了解网络协议:TCP/IP详解
从零开始了解网络协议:TCP/IP详解 在当今数字化的时代,网络协议已经成为我们生活中不可或缺的一部分。作为互联网的基础,网络协议规定了数据如何在不同的网络设备之间传输。TC...【详细内容】
2024-02-01    简易百科  Tags:TCP/IP   点击:(62)  评论:(0)  加入收藏
BGP路由属性:互联网路由的灵活控制器
在互联网的庞大网络中,边界网关协议(BGP)是确保不同自治系统(AS)间路由信息有效交换的关键协议。然而,BGP的功能远不止于此。其核心组成部分,即BGP路由属性,赋予了BGP强大的灵活性,使...【详细内容】
2024-01-26  诺诺爱生活    Tags:互联网路由   点击:(45)  评论:(0)  加入收藏
简易百科之什么是网络延迟?
简易百科之什么是网络延迟?随着互联网的普及和发展,网络已经成为我们生活中不可或缺的一部分。然而,我们在使用网络时可能会遇到一种情况,那就是网络延迟。那么,什么是网络延迟呢...【详细内容】
2024-01-24    简易百科  Tags:网络延迟   点击:(163)  评论:(0)  加入收藏
网络延迟与网络速度有什么区别?分享具体的答案
通常,许多人抱怨网速测试。速度还是不错的,但是他们玩游戏的时候怎么会卡住,还是断开连接等等问题,这一系列问题始终困扰着大家。那么,网络延迟与网络速度有什么区别呢?请不要担心...【详细内容】
2024-01-24  萌新小郭    Tags:网络延迟   点击:(54)  评论:(0)  加入收藏
揭秘IP地址的网络威胁与攻击类型
在当今数字化时代,网络攻击已经成为网络安全的一大挑战。IP地址,作为互联网通信的基础,也成为网络威胁和攻击的焦点之一。本文将深入探讨不同类型的网络威胁和攻击,以及如何防范...【详细内容】
2024-01-22  IP数据云    Tags:IP地址   点击:(88)  评论:(0)  加入收藏
站内最新
站内热门
站内头条