1. 从“发包裹”说起TCP/IP协议到底是什么我先抛个问题你有没有想过当你在浏览器里敲下域名、按下回车到页面刷出来这中间到底发生了什么如果有一天面试官这么问你你怎么回答答案就藏在一个词里——TCP/IP协议。它不是单个协议而是一整套“网络通信规则”。你可以把它理解成快递行业的整套运作流程你写了收货地址IP填了寄件人源IP快递员按地址跑腿路由快递面单上还得有“收件人姓名”端口如果东西贵重还得保价、签收确认TCP如果只是普通小件丢了也不心疼那就发普通快递UDP。这套规则从头到尾规定了“怎么包装、怎么填单、怎么跑线路、怎么验货”缺一环你的数据就送不到对的地方。这篇文章是写给谁的给所有被“TCP/IP”这四个字劝退过的同学。不管你是刚入行的后端开发、运维小白、网工实习生还是产品经理想搞懂点底层逻辑都能看。我会用“寄快递”“打电话”这类生活类比把四层模型、IP地址、端口、三次握手、四次挥手这些看似高大上的东西拆开揉碎最后还会带上我在实际抓包、排障时踩过的坑。保证你读完不是“好像懂了”而是真能上手排查问题。2. 先把骨架搭起来TCP/IP四层模型到底分了啥2.1 为什么非要分层不分行不行早年网络设备百花齐放各家有各家的协议不同厂商的设备之间根本没法互通就像电话刚发明时不同公司的电话网接不到一块。为了解决这个问题业界定了一套公共规范让“会说人话”的设备都能互相通信。分层的核心思路是每个人只管自己那一层的活儿上层不关心下层怎么实现下层也不理解上层在说什么。就好比快递小哥不用懂你的电脑是怎么把网页生成出来的他只管送包裹而你寄快递也不用懂卡车怎么走高速你只需要填单子。TCP/IP模型常被简化成四层层级名字职责你熟悉的东西第4层应用层生成数据面向用户HTTP、DNS、FTP、SSH第3层传输层端到端的可靠传输或尽力传输TCP、UDP第2层网际层寻址与路由找到目标主机IP、ICMP、ARP第1层网络接口层物理传输比特流转成电信号/光信号以太网帧、WiFi注意TCP/IP模型是事实上的工业标准而OSI七层是理论上的教学模型。考试归考试工作中你只用记住这四层就够了。2.2 每一层到底干了什么事拿你打开百度首页举例一个数据包的“旅行”过程是这样的应用层浏览器生成一个HTTP请求要获取baidu.com的主页内容。传输层TCP把这段请求切成合适大小的“数据段”给它编号保证顺序还要建立可靠的连接信道。网际层IP协议在数据段外面套上IP头写上源IP和目的IP相当于写了寄件地址和收件地址。网络接口层再封装成帧通过网卡变成光信号/电信号走物理线路出去。到了百度服务器那边顺序反过来物理层收到信号剥开帧剥开IP头剥开TCP头最后把HTTP请求交给百度后端的程序处理。每一层只处理自己关心的头部信息然后把剩下的“包裹”往上传——这就是“分层”最优雅的地方各层独立演进互不干扰。2.3 为什么OSI七层模型反而没统一世界你可能听过OSI七层模型它把网络分成七层看起来更严谨为什么实际用的是TCP/IP呢原因很现实OSI太完美落地太慢TCP/IP先实用主义地跑起来了而且逐层开放、免费、代码开源Linux和Unix生态全站TCP/IP。等OSI标准磨磨蹭蹭定稿时世界已经被TCP/IP占领了。所以你现在看到的互联网骨子里跑的是TCP/IP这套简洁的分层方案。3. 核心主角IP地址、端口、MAC地址到底在干嘛3.1 IP地址就是“门牌号”但它是有版本的IPv4是32位约43亿个地址长这样192.168.1.1。今天早就不够用了。IPv6是128位数量多到可以给地球上的每一粒沙子分配地址。普通用户见到最多的是IPv4但服务器、云主机、运营商网络都在悄悄往IPv6迁移。IPv4地址还分公网IP和内网IP。你家路由器后面的设备全是内网IP比如192.168.x.x、10.x.x.x、172.16.x.x。这些地址在外面路由上不可路由靠路由器做NAT网络地址转换才能上网。这就是为什么你家里的电脑没法被外网直接访问——因为外网根本不知道你这个内网IP是谁。3.2 端口光有IP还不够你得说清楚找“哪个人”假设IP是公司地址那端口就是部门分机号。你访问一台服务器的80端口跑的是Web服务22端口跑的是SSH服务3306是MySQL。IP 端口组合比如 192.168.1.10:8080才能精确定位到一台机器上的一个具体应用。端口分为著名的0-1023需要特权如80、443、注册端口1024-49151、动态/私有端口49152-65535。客户端发起请求时会随机从高位端口选一个出厂跟服务器通信。所以你在服务端日志里看到的“源端口”经常是那种稀奇古怪的四位数。3.3 MAC地址快递到了小区门口还得靠门牌找具体楼层IP负责跨网络寻址MAC地址负责“最后一跳”。网络包一层层转发时到达本地网络要用ARP协议把“目标IP”翻译成“目标MAC地址”然后帧才能在以太网里播出。网上找IP本地靠MAC是这个体系里特别容易混淆的一点。注意IP地址是逻辑的、可以变的MAC地址是物理的、出厂烧录的。换了一台电脑同一个IP会有不同的MAC永远不要用MAC当业务标识。4. 传输层两大护法TCP和UDP的相爱相杀4.1 TCP面向连接可靠像打电话TCP能保证数据不丢、不乱序、不重复靠的是三个机制握手建立连接、序列号管理、确认重传。我讲讲经典三次握手SYN、SYN-ACK、ACK客户端发送SYN同步序列号报文携带初始序列号X告诉服务器“我要连你”。服务器回复SYN-ACK携带自己的初始序列号Y同时确认收到了XACKX1。客户端再回一个ACK确认收到Y。此时双方连接建立。为什么是三次不是两次因为双方都得确认“我能发数据你能收到、你能发数据我能收到”。两次握手只能保证“客户端确认服务器能听”服务器那边不知道自己的回复客户端有没有收到容易造成半连接和资源浪费。4.2 四次挥手再见为什么要挥四次断开连接时要四次挥手FIN、ACK、FIN、ACK主动关闭方比如客户端发FIN表示“我没有数据发了”。被动方回ACK表示“我知道了”。但此时被动方可能还有数据没发完所以连接还没断。被动方数据发完后发FIN表示“我这边也没数据了”。主动方回ACK之后等待2MSL才完全关闭。FIN和ACK分开成两步是四次而不是三次的根本原因——TCP是双工通道两个方向需要各自独立地关闭。2MSL等待是个坑如果主动方直接关闭最后那个ACK丢了被动方会一直重发FIN浪费资源。等待2MSL能保证最后的ACK足够到达对端同时也能让旧连接上的延迟包在网络里消亡不至于污染新连接。4.3 UDP无连接尽力而为像寄明信片UDP没有握手、没有确认、没有重传直接“写地址、投递”。好处是开销小、延迟低坏处是丢包了对方不知道。语音通话、视频直播、DNS查询、游戏帧同步都用UDP因为实时性比可靠性重要。游戏里少一帧画面可以接受但如果画面为了“等重传”卡住体验直接爆炸。4.4 TCP vs UDP 怎么选一张表说明白对比项TCPUDP连接状态有连接无连接可靠性可靠有序尽力而为无序传输效率低一点点高应用场景HTTP、FTP、邮件、数据库直播、游戏、DNS、物联网上报拥塞控制有无实际工程里还有个“中间态”UDP上叠加QUIC。QUIC是在UDP之上实现可靠传输加密快并且可靠新一代HTTP/3就基于QUIC。这说明TCP和UDP不是非黑即白工程上完全可以自己叠加协议。5. 应用层的幕后功臣DNS和HTTP的配合5.1 DNS把baidu.com翻译成IP的“电话簿”人记域名机器记IP。DNS就是一个全球分布式电话簿。你输入www.baidu.com后本地DNS服务器会一层层去问根DNS、顶级域DNS、权威DNS拿到IP后才开始真正的HTTP请求。这过程叫“递归查询”和“迭代查询”。DNS是UDP 53端口但区域传输用TCP 53响应如果太大也会切到TCP。我之前排查过一个“网页加载偶尔超时”的故障查了半天发现是本地DNS的UDP响应被防火墙丢包改用TCP后就好了。DNS不总是UDP很多人在这栽过跟头。5.2 HTTP与HTTPS协议栈的“最终输出”HTTP跑在TCP上默认80端口HTTPS跑在TCP上但外面套了TLS默认443端口。你看到的网页请求本质上是HTTP请求 TCP数据段 IP数据报 以太网帧四层各加一个头逐层封装。用抓包工具看就是一个“洋葱”从最底下物理帧一路剥开最后露出HTTP的内容。5.3 你随时随地都在用TCP/IP但没感觉到手机看视频、聊天软件发消息、扫码付款、远程打卡……每天高频使用的App底层全是TCP/IP协议栈。没有这套协议互联网设备就是一座座信息孤岛。理解了协议栈你再学什么Nginx、Docker网络、K8s Service会发现全是TCP/IP的延伸——K8s的Service就是基于IPVS/iptables做转发本质还是IP端口那套逻辑。6. 实战5分钟排查一次网络故障的完整思路6.1 故障排查的第一步不是重启路由器而是分层定位我用这套思路解决过无数次线上问题。拿到“上不了网”的反馈按顺序排查先看网卡状态ip addr有没有拿到IP地址接口是否UP。看网关通不通ping 网关IP。通了说明本机到路由器没问题。看外网通不通ping 8.8.8.8或ping 223.5.5.5。通了说明路由和物理链路正常。看DNS解析正不正常nslookup baidu.com解析出IP说明DNS没问题。如果是某个端口不通用telnet ip 端口或nc -vz ip 端口测试。这套“从底层往上ping从上层往下查”的思路比瞎猜高效百倍。6.2 常用命令人人都会用但不一定用明白ping验证三层连通性 最基本的路由质量。注意ping通不代表端口通端口是四层的事。tracerouteLinux/tracertWindows看数据包经过哪些路由节点。哪一跳延迟高故障点基本就在那附近。ss -tunlp/netstat -tunlp本机监听端口和连接状态。tcpdump抓包利器。比如抓80端口的包tcpdump -i eth0 tcp port 80 -nn -c 100。dig/nslookupDNS查询适合排查解析问题。6.3 用tcpdump现场抓一次三次握手为了方便演示我假设你要访问example.com。开两个终端终端1sudo tcpdump -i eth0 tcp port 80 -nn终端2curl http://example.com正常情况下你会看到IP 你本机IP.随机端口 目标IP.80: Flags [S] IP 目标IP.80 你本机IP.随机端口: Flags [S.] IP 你本机IP.随机端口 目标IP.80: Flags [.]S是SYNS.是SYN-ACK.是纯ACK。看到这3条说明三次握手完成了。如果只看到第一条SYN没有后续响应说明目标端口被防火墙拦了或者服务根本没启动。这个技巧我在线上排查时用了无数次比看日志直观多了。6.4 常见协议状态速查ss -ant输出里的TCP状态字段含义要心里有数状态含义常见原因LISTEN服务在监听端口正常ESTABLISHED连接已建立正常通信中SYN_SENT发出SYN未收到回包目标不可达、防火墙丢包SYN_RECV收到SYN未完成握手半连接队列满、服务过载TIME_WAIT主动关闭方等待2MSL正常但量大要调参CLOSE_WAIT被动方等待应用关闭连接代码没关socket非常经典的故障我在线上见过大量CLOSE_WAIT堆积的场景一般是服务端代码没有正确关闭连接导致的排查方向就是看程序有没有释放socket资源。7. 工作中最容易踩的TCP/IP坑7.1 内网IP不够用网段划分记住这几个192.168.0.0/16最常见的家庭网络。10.0.0.0/8大企业、云VPC常用。172.16.0.0/12老网络里偶尔见。子网掩码决定一个网段里有多少可用主机。比如192.168.1.0/24前24位是网络号后8位是主机号可用主机最多254台。规划VPC时记住先确定掩码再定网段不要随手写个/24然后发现机器不够用。7.2 网关、路由、NAT搞混必出事网关是出口路由是“下一跳”的决策逻辑NAT是地址转换。家里网关一般是路由器内网IP云上VPC网关一般是网络入口节点。路由表则决定这个包朝哪个方向走ip route show如果路由表异常或者默认路由丢了网络就直接断了。我在K8s集群里见过很多节点网络异常排查第一步永远是ip route | grep default默认路由没了容器网络再花哨也白搭。7.3 IPv6来了你的服务还只监听IPv4吗现在很多云服务默认打开IPv6但你的Nginx或Java服务可能只监听IPv4的0.0.0.0:80导致IPv6地址访问不通。排查方法ss -tlnp | grep :80如果监听的地址是::ffff:0.0.0.0:80说明双栈兼容如果只有0.0.0.0:80IPv6访问就会被拒。解决办法通常是同时监听IPv6的[::]:80。7.4 TCP缓冲区、MTU问题像隐形炸弹TCP有个机制叫滑动窗口缓冲区发送方和接收方都有固定大小的缓存区。如果缓冲区设置太小大文件传输效率就很低。而MTU最大传输单元通常为1500字节如果你的机器和路由器MTU不一致就会出现“能上QQ但打不开网页”的诡异现象往往是分片被丢或者DF位导致的问题。遇到这种问题按这个思路调ifconfig eth0 mtu 1400临时改小MTU测试如果正常就是MTU不一致再把路由器MTU调成一致即可。8. TCP/IP学会后下一步该往哪走TCP/IP是网络世界的“底层方言”但光懂协议不会用学习效果打五折。建议照着做一遍在本机抓一次访问某个网站的完整包对照本文看TCP握手、HTTP请求、TCP挥手。搭一个最简单的Python HTTP服务器用tcpdump观察它和浏览器的通信过程。学会看ss -ant状态模拟断网、防火墙规则观察状态怎么变化。手动配一次静态IP、网关、DNS强迫自己理解三层要素。如果把这套流程走完你已经比很多工作两三年的开发更懂网络了。下一阶段可以学Nginx反向代理、负载均衡、Docker网络模型、K8s Service本质上都是TCP/IP的“业务编排”。最后再分享一个小技巧排查网络问题的时候心里永远装着“分层”这两个字从物理到应用一层层排除效率会翻倍。我见过太多人一上来就重启、重装、清缓存结果问题出在一台设备MTU不对上。TCP/IP这玩意儿值钱的地方不在于背概念在于出问题的时候你能看着数据包叙述完整的故事。
