尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从聊天消息到数据包:网络应用原理与抓包排查实战

从聊天消息到数据包:网络应用原理与抓包排查实战 1. 从一个聊天消息说起网络应用到底做了什么你有没有在微信或者QQ群里发过一条消息正常情况下点一下发送对方一两秒就收到了。但如果你从来没琢磨过这一两秒背后发生了什么那我建议你认真看完这篇内容。因为我说的“网络应用原理”本质上就是要回答一个问题你手机屏幕上这些聊天App、购物App、视频App它们的数据到底是怎么跑起来的。很多人刚开始接触网络知识时最容易踩的一个坑就是把“网络应用”和“写网页”“调接口”混为一谈。实际上网络应用是一整套体系它至少涉及三件事消息怎么编码、消息怎么寻址、消息怎么传输。把这三件事拆开看你就会发现一个聊天消息从你的手机飞到对方的手机中间要经历一次非常精密的“接力旅行”任何一个环节出了问题消息要么发不出去要么发出去乱码要么被路由丢在半路。这篇文章适合谁两类人。一类是刚学计算机网络、被各种协议名词绕晕的学生党另一类是已经在写代码却不太清楚自己写的HTTP请求在底层到底经历了什么的开发者。我尽量不堆教科书术语用实际抓包、命令排查、现场演示的方式把“聊天发消息”这件事掰开揉碎让你看完之后能对着抓包工具说出每一步的原理遇到网络问题也不再两眼一抹黑。既然要从“数据怎么跑起来”入手我们就不绕弯子直接进入正题。2. 网络应用背后那趟“消息快递”的完整路线2.1 一次发送动作被拆成了多少个环节把你在聊天框里打出的“在吗”这两个字拆开来数一数从按下发送键到对方看到消息至少有六个环节在协同工作你的手机把文字转成二进制数据打成一个数据包系统通过Wi-Fi或移动网络把包发给附近的基站或路由器这个包经过运营商骨干网络或者企业路由设备一路跳转期间要查地址、做路由决策可能经过十几台路由器包到达对方手机所在的网络由当地接入设备交付对方的微信客户端解析数据把“在吗”渲染在屏幕上。这六个环节涉及的关键问题就是数据包怎么知道对方的手机在哪路由器凭什么决定把包往哪个方向转发两台设备怎么保证数据完整不丢、顺序不乱所以学网络应用原理第一步不是去背TCP三次握手的状态码而是要把这个“整体链路”画在脑子里。我见过太多人面试被问“从输入URL到页面显示中间发生了什么”时只会背到DNS解析就卡壳。这里给你一个更完整的答案框架从应用层发起请求到传输层选择TCP或UDP并加上端口信息再到网络层封装出IP地址最后到链路层把包转成电信号发出去——对方收到后再反向一层一层拆开。整条链路全串起来才叫一次完整的网络通信。这个框架就是你理解所有网络应用的骨架。不要着急去纠结某个协议先把“打包装箱、填写地址、交给运输、收货拆箱”这个直觉建立起来。2.2 三个核心要素地址、端口、协议既然说的是网络应用那围绕应用层通信有三个核心要素是你绕不开的。你可以把它们类比成寄快递时必需的信息。第一个是地址。网络上的每台设备都需要一个“门牌号”不然数据包不知道该往哪送。这个门牌号就是IP地址。IPv4时代地址长这样192.168.1.10032位全球加起来也就四十几亿个早就不够用了所以现在大家都在迁移IPv6地址长度扩展到128位近乎无限。第二个是端口。一台手机或者服务器上可能同时跑着微信、浏览器、邮箱客户端如果一个设备只有一个IP数据包到了之后如何区分是给微信还是给浏览器的这就需要端口号。IP负责把数据包送到设备端口负责把数据包送给设备上对应的那个App或者服务。你可以把整个链路想象成寄快递到一座大楼IP是楼址端口是具体的房间号。第三个是协议。双方要通信必须约定好“怎么说”。这个约定就是协议。两个人聊天一个只说中文一个只说英文怎么交流网络设备也一样所以就有了HTTP、TCP、UDP、IP、DNS这些协议族每一层都有自己的“语言规范”。网络应用原理说穿了就是研究这些协议如何在不同的通信场景下各司其职。很多教材会把这三个要素掰成很多小节但我建议你先用一个最小场景去理解。比如你在浏览器里输入 https://example.com它做的事很简单通过DNS拿到IP地址向这个IP的443端口发起TCP连接然后双方通过HTTP协议交换数据。所有复杂的网络应用本质上都是这个最小场景的变种。2.3 为什么我推荐用“快递类比”理解分层网络通信这个领域里最容易把人绕晕的就是“分层”。TCP/IP有四个层OSI有七层每层之间还有各种协议。初学者一看到层就头大觉得抽象。我的建议是把每一层理解为一次快递运输流程中的不同角色。你想象一下你在淘宝上买了一样东西商品本身相当于应用层的数据比如聊天消息、网页内容、文件商家把商品装进纸箱贴上内部单据这一层相当于传输层它会给数据加一个“端口信息”确保能送达到目的App纸箱到了快递网点工作人员贴上快递面单写清收发件地址这相当于网络层封装IP地址用于设备间寻址快递车在高速公路上行驶时扫面单、分配路线这相当于链路层和物理层负责数据真正的传输。关键点在于每一层只需要处理自己的“包裹”不需要关心其他层怎么做。商家不用自己开车送货快递公司不用管商品填充了什么泡沫买家收到货也不需要关心包裹走的是哪条高速。这种“高内聚低耦合”的结构让任何人都可以在任意一层做优化而不影响其他层。所以当你看一个网络问题排查案例时第一件事永远是问这个问题出现在哪一层是应用层的数据格式错了还是网络层的路由断了又或者是链路层的信号干扰你分层分得越清楚排查范围就越小解决效率就越高。3. 核心细节详解协议栈里那些你躲不开的角色3.1 TCP和UDP一个像挂号信一个像群发广告网络应用原理中传输层是你无论如何也绕不开的一层。而在传输层TCP和UDP就是两个最核心的角色。TCPTransmission Control Protocol就像挂号信每一封信都有编号发出去之后如果对方没有回执发信方会重发收齐了会按编号排序组装。它提供的服务是“可靠的、面向连接的”传输。怎么做到可靠靠的是三次握手建立连接、数据确认应答ACK、超时重传、滑动窗口控制流量。代价也很明显每次通信都要先“打招呼”、传输过程中还要额外传递很多控制信息速率和资源开销都不小。UDPUser Datagram Protocol则更像在大街上往人群里撒传单它不管对方收没收到也没有连接的概念。发出去就完了速度极快但数据丢失了不重传顺序乱了也不调整。所以直播、语音通话、在线游戏这类对实时性要求高、能容忍少量丢包的应用会优先选UDP。而文件传输、网页访问、收发邮件这种一个字节都不能错的应用几乎都是TCP的天下。很多讲网络原理的文章会把TCP和UDP的区别做一张大表从连接性、可靠性、传输效率到应用场景列一堆。不过我更建议你用真实场景去记你下载一个文件必选TCP因为文件坏了没法用你打网络电话会更倾向UDP因为如果其中一秒的语音丢了要重传那这一秒的空白比丢音更让人难受。网络应用选型时怎么选核心就一句话可靠性优先选TCP实时性优先选UDP。3.2 HTTP与HTTPS聊天记录在网络上并不加密到了第七层还是第四层别急这里的应用层是直接面向用户的那一层。你可能听过HTTP和HTTPS它们是最常见的应用层协议承载的是浏览器里的网页、手机App的接口请求。而聊天类应用虽然看起来是自定义协议但在传输层之上同样遵循这个逻辑。HTTP的工作模式其实特别简单就是你发一个请求服务器回一个响应。标准的流程是客户端发起一条Request里面带着方法GET、POST、PUT、DELETE等、URL、请求头和请求体服务器处理完再返回一个Response里面有状态码200、301、404、500等、响应头和响应体。但是HTTP本身是明文传输的。这就意味着你在一个不安全的Wi-Fi环境中访问一个HTTP网站中间任何设备都能够截获你传输的数据。浏览器地址栏里如果显示“不安全”通常就是因为这个站点还在跑HTTP。HTTPS其实就是HTTP加了一层SSL/TLS加密。什么叫加了一层可以简单理解成在发送真实数据之前客户端和服务器之间先进行了一次密钥协商协商出一个只有双方知道的会话密钥之后传输的数据全部加密。没有密钥的人就算截获了数据看到的也是一堆无法还原的密文。2024年之后各大互联网平台基本已经全面启用HTTPSHTTP只适合用来做本地调试。我用curl命令看一个HTTP请求时经常通过 -v 参数来检查TLS握手是否成功这里分享一个最常用的调试指令curl -v https://example.com执行后你会看到输出里有一段“SSL connection using TLSv1.3”这说明TLS握手已经完成。如果这里报证书错误或者握手失败问题往往出在证书链或者系统时间上。3.3 DNS解析全过程从域名到IP的“翻译官”大家都觉得域名好记比如 baidu.com、qq.com但网络层设备只认IP地址。于是就需要DNSDomain Name System来完成翻译。这里最容易被忽略的一个点是DNS解析不是一个“一步到位”的过程它会经过一套缓存体系。以你在浏览器访问 www.example.com 为例完整流程是这样的浏览器先查自己的内存缓存看之前有没有解析过这个域名没有命中就查询操作系统的hosts文件和系统DNS缓存还没有就把请求发给本地配置的DNS服务器ADSL拨号或者手机网络时通常由运营商分派本地DNS服务器如果也没有缓存会替你去问根域名服务器根服务器告诉它.com服务器的地址它再去问.com服务器得到example.com的权威服务器地址最后问权威服务器拿到www.example.com对应的具体IP地址。这整个过程对用户是透明的但对网络性能影响极大。DNS解析时间过长会让网页看起来“很卡”。我自己排查“打开网页白屏”问题的时候第一步往往不是看服务器负载而是先用nslookup或者dig命令看看DNS解析耗时正不正常。常用排查命令nslookup example.com dig example.com如果解析速度异常慢多半是本地DNS服务器出问题或者被污染了可以试着换一个公共DNS像114.114.114.114或者8.8.8.8再对比一次。需要注意公共DNS服务商有很多建议选择有明确服务商背景的地址来测试。3.4 一个IP地址如何找到对应的应用NAT与端口映射在讲网络应用的时候有一个非常现实的问题大部分家用电脑、公司内网服务器用的都是私有IP地址比如192.168.x.x这些地址无法直接在公网路由。那外网的服务器怎么把数据回传给你这里最核心的机制就是NATNetwork Address Translation。NAT设备通常是路由器它维护一张映射表把你内网设备的IP和端口映射成路由器公网IP上的一个临时端口。当你的设备发起对外连接时路由器会记录这个映射响应数据回来时路由器一看端口再反向替换成内网设备的IP和端口。很多人在家搭建服务比如内网跑了一个网站想让外网的朋友访问会遇到“端口映射”的概念。所谓端口映射就是手动在路由器NAT表里加一条规则把公网IP的8080端口转发给内网某台机器的80端口。有了这条规则外网用户访问你路由器公网IP的8080端口就能直达你内网的网页服务。做这类配置时最容易疏忽的是运营商常常给家庭宽带分配的是动态公网IPIP变了映射就失效了。所以我的建议是内网调试用静态内网IP加端口映射足够真要长期对外提供服务还是买一台有固定公网IP的云服务器更靠谱省得天天被动态IP搞得措手不及。4. 实操观察在真实环境里看数据怎么跑起来4.1 环境准备与抓包思路前面讲了那么多理论这一节我们动手。看懂网络应用原理最好的方式就是亲眼“看到”一个数据包从发起到接收的完整过程。我会用一个最简单也最直观的实验在本地环境里模拟一次网络请求用抓包工具把传输过程抓出来给你看。先说我用的环境一台装有Linux的虚拟机以及Wireshark这个网络分析工具。Wireshark是图形界面的它的命令行版本叫tshark。如果你手头没有虚拟机直接用自己电脑的抓包工具也能跟着操作只要确保实验环境是干净的、流量可控就行。我们做实验的目标很明确从一个App或者命令行访问一个网站抓取整个过程中的DNS请求、TCP握手、TLS握手和HTTP数据交换分析每一段数据包的特征。实验前有一个非常重要的提醒抓包时如果不过滤你看到的将是海量广播包、背景流量、系统服务发出的零散包很难找到目标。所以抓到包之后要立刻加过滤规则。比如我先在终端里执行一条抓包命令把结果保存到文件里sudo tcpdump -i eth0 -w /tmp/http_test.pcap host example.com这个命令只在eth0网卡上抓与 example.com 这个主机通信的包并写入文件。抓大约10秒后按CtrlC停止。4.2 现场还原一次完整的HTTPS请求为了演示我这里模拟一次最典型的HTTPS访问流程。你先执行抓包命令然后再开一个新的终端窗口执行curl -I https://example.com命令执行完回到抓包终端停止抓包然后用Wireshark打开保存的pcap文件。接下来你会看到顺序非常清晰的几组数据包。第一段是DNS查询。当你输入 https://example.com 时系统首先并不知道这个域名对应的IP是多少于是它会向DNS服务器发一个UDP数据包查询目标端口是53。DNS服务器收到后会回复一条UDP响应里面直接带着example.com对应的IP地址。抓包工具里这一步表现为一对一来一回的数据包。观察它们你会发现DNS报文的长度很短通常只有几百字节。第二段是TCP三次握手。拿到了服务器IP后客户端会发起TCP连接目标是80端口或者443端口。三次握手的过程正是一个网络原理面试题的经典素材第一次客户端发送一个SYN包给服务器表示“我想建立连接”标志位是SYN1第二次服务器回复SYNACK包表示“收到你的请求我也同意”标志位是SYN1、ACK1第三次客户端再回复一个ACK包表示“连接正式建立”。你可以看到三个包带着不同的TCP flags。有人问为什么一定要三次而不是两次因为要防止已经失效的连接请求突然又传到服务器导致服务器白白建立资源。这个点在面试里很常考实操中抓一次包就能看明白了。第三段是TLS握手。由于请求的是HTTPSTCP连接建立后并不会立刻传业务数据而是先进行TLS协商。你会看到客户端先发ClientHello里面写着支持哪些加密套件服务器回ServerHello选定一组加密算法并发送证书然后双方交换密钥最后用ChangeCipherSpec通知对方“之后的消息都是加密的了”。这段过程在抓包工具里会有明显的多个连续报文。第四段才是HTTP请求和响应。在你用curl -I命令的情况下发送的是HEAD请求服务器会返回HTTP状态码和响应头。比如200 OK表示一切正常。如果你访问的是一个普通HTTP网站就省掉了第三段TLS握手整个流程会更快但代价是数据明文传输你甚至能在抓包里直接看到你提交的账号密码。4.3 Wireshark里的常见过滤和分析技巧对新手来说抓包最劝退的一点是看不懂数据包列表。实际上你要紧紧抓住一个核心维度就是Protocol列和Info列。Wireshark的显示过滤器功能非常强大我平时至少会和这几个过滤器打交道DNS信息输入 dns只显示DNS协议的包适合看域名解析的结果和耗时TCP握手包输入 tcp.flags.syn 1快速过滤出SYN握手包HTTP请求输入 http直接查看明文HTTP协议的请求和响应指定IP通信输入 ip.addr 192.168.1.1只看与该IP的往来流量。另外Wireshark支持“追踪TCP流”功能在任意一个TCP报文上右键选择Follow - TCP Stream就能把整个TCP连接中传输的应用层数据拼出来。如果抓的是HTTP流量这里就能直接看到完整请求头和响应头甚至可以还原网页源码。这在调试前后端联调问题时尤其有用。我之前排查过一次前端上传文件失败的问题从浏览器控制台看请求报错后端日志又没记录到任何请求最后用Wireshark抓包发现TCP层面就开始分包重传了原因是MTU设置不对导致大包传输一直被丢弃。这类问题如果不抓包光靠看代码可能排查好几天。4.4 用命令行工具完成网络检测三板斧在没有图形界面的服务器上Wireshark用不了这时候我最常用的排查命令有三组ping、telnet、curl。这组命令组合起来基本能定位80%的网络故障。第一板斧是ping它用来检测目标主机是否在线、网络延迟高不高。ping命令发的ICMP协议包不需要建立TCP连接所以只要有网络路由存在目标主机一般就会回应。一个典型的输出如下$ ping -c 4 example.com PING example.com (93.184.216.34) 56(84) bytes of data. 64 bytes from 93.184.216.34: icmp_seq1 ttl56 time24.3 ms 64 bytes from 93.184.216.34: icmp_seq2 ttl56 time24.1 ms看到Reply或者64 bytes from说明网络通路是通的。如果请求超时并不一定代表主机挂了可能是对方禁了ICMP协议比如很多云服务器默认在安全组里禁Ping。第二板斧是telnet用来测试目标IP和端口的连通性。比如你想知道一台服务器上的80端口是否开启可以执行 telnet 服务器IP 80。如果端口通终端会进入一个黑屏界面或者显示Connected如果不通会提示Connection refused或者直接超时。我用这个命令来检测数据库端口、Redis端口、Web端口是否从当前网络可达。第三板斧是curl它不仅能发起HTTP请求还能查看响应码、请求头、TLS证书等信息。当你需要排查一个接口是通的但返回状态码不对时curl的 -v 参数是最好的朋友。看响应体加 -d自定义请求头加 -H设置超时加 --connect-timeout。这些参数我背得滚瓜烂熟因为它们基本上是网络工程师和后台开发者每天都要用的。5. 网络应用排查实战常见的坑与避坑技巧5.1 数据发不出去先看这五类问题很多人写网络应用时遇到“数据发不出去”就抓瞎其实这类问题无外乎五个原因。我把它们整理成一个排查顺序你可以直接照做。第一类是地址问题。检查目标IP、域名拼写是否正确。尤其在容器环境下很容易出现复制粘贴少了一个字母导致解析失败的情况。第二类是端口问题。目标端口的服务有没有启动防火墙有没有放行这个端口。Linux上可以用 ss -lntp 查看当前监听端口Windows上可以用 netstat -ano 对应查看。第三类是网络安全策略问题。云服务器一般都有安全组安全组规则里的入站、出站权限要单独看本地防火墙比如iptables或者firewalld也要检查。和本地防火墙不同安全组是在服务商侧生效的本机命令看不到它。如果从外部连不上你的服务先确认安全组放开端口再检查本机监听。顺序错了就会白折腾。第四类是协议匹配问题。客户端用了UDP但服务器监听的是TCP或者HTTP请求发到了HTTPS端口。这类问题抓包看协议标志就能快速发现。第五类是路由问题。数据包能出去但没有到达目标网络的路径。用 tracertWindows/ tracerouteLinux就能看到包到底卡在哪一跳。排查的时候不要一上来就抓包先通过分层思维缩小范围这样效率最高。5.2 聊天消息明明发出去了对方却收不到注意这里是文章重点。很多即时通讯类应用在“消息送达”场景中都采用了应用层确认机制。什么意思就是客户端把消息送给服务器后服务器会返回一个ack但此时并不代表对方手机已经收到只代表服务器接收成功。服务器再往对方推送时还有自己的确认机制。如果你遇到“消息显示已发送但对方就是不回”的情况这往往不是一个网络传输层的问题而是一个“消息状态同步”的应用层协议设计问题。经验是给聊天框写一个“已发送/已送达/已读”的三态标识需要分别在消息到达服务端、到达接收端、接收端阅读时触发回调。为了不阻塞主流程这些状态消息往往走后台上报不走用户的聊天消息通道。另一个常被忽视的问题是弱网环境下的策略选择。当手机信号差到一定程度TCP连接频繁超时重传时消息会反复“发送中”。很多App的做法是先把消息落到本地数据库等网络恢复后再批量重发而不是傻傻地在当前界面等同步完成。这既是网络应用设计的问题也是用户体验设计的问题。理解了TCP重传机制和弱网特性你就不会在代码里写出“网络一断就丢消息”的方案了。5.3 我踩过的三个隐蔽坑一、DNS缓存导致的“本地好了线上没变”。开发环境里我经常切换不同服务器环境每次切换后域名指向的IP会变。碰到“代码没问题但访问结果永远是旧版”时先别急着重启服务有可能是你系统里的DNS缓存还没过期。Windows中我用 ipconfig /flushdns 清理缓存macOS用 sudo dscacheutil -flushcacheLinux则是 systemd-resolved --flush-caches。实践下来这个操作解决了很多“诡异”问题。二、MTU过大导致的大包被静默丢弃。这个坑非常隐蔽几十个包能过某一个包超过1500字节就卡住表现就是文件上传经常断、网页打开慢、某些接口超时。用 ping -s 1472 目标IP 去测如果提示需要分片但不允许分片基本就能确认是MTU问题。在服务器上把网卡MTU值调到1400左右情况往往会立刻缓解。三、并发连接数打满导致的“应用假死”。网络应用不只是“发请求”这么简单你还需要考虑端口资源、文件描述符上限。Linux下每个TCP连接都是一个文件描述符默认限制可能只有1024高并发场景一下就满了。我遇到过几次线上应用“明明进程活着但所有请求都超时”的情况最后用 ulimit -n 查看发现文件描述符早就爆了。调高这个限制配合keepalive复用TCP连接能明显提升应用吞吐量。6. 从原理到实战的个人经验总结这篇文章写到这里一个从“聊天发消息”到“数据怎么跑起来”的完整链路你已经看到了。说实话我最初学网络应用原理的时候也被各种协议层级搞得迷迷糊糊。后来自从开始频繁抓包、频繁在服务器上做网络排查把抽象的概念和具体的报文对应起来之后这些知识才真正内化成了自己的东西。现在我处理网络类问题有一个习惯先问自己“这个故障在TCP/IP模型的哪一层”。如果ping通了问题大概率不在网络层而在传输层或应用层如果底层TCP连接都建不起来那再查应用层就是白费功夫。分层思维不是考点而是解决复杂系统问题的基本能力。如果你是真的想把网络应用原理吃透我的建议是去找一个你每天都在用的App想尽办法去观察它一次请求的完整生命周期。从打开App那一刻起看看它请求了多少域名、建立了多少TCP连接、传输了什么协议的数据。这个过程会花掉你一个下午的时间但收获会远远超过你背十遍协议文档。网络这种东西看再多书都不如抓一次包来得实在。
返回列表