<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>TCP/IP on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/tcp/ip/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 09 Dec 2017 10:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/tcp/ip/index.xml" rel="self" type="application/rss+xml" /><item>
      <title> TCP/IP 学习总结与避坑指南</title>
      <link>https://ftmao.com/blog/bookstore/tcp-ip-illustrated-notes/</link>
      <pubDate>Sat, 09 Dec 2017 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/tcp-ip-illustrated-notes/</guid>
      <description>&lt;h1 id=&#34;tcpip-学习总结与避坑指南&#34;&gt;TCP/IP 学习总结与避坑指南&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;最近华为项目交付碰到各种头大的网络问题，现在整理下TCP/IP相关知识。参考书籍：W. Richard Stevens《TCP/IP 详解 卷1：协议》、W. Richard Stevens《Unix 网络编程 卷1：套接字联网 API》&lt;br&gt;
目标读者：刚接触网络编程，或者学了很多概念但总觉得「协议栈串不起来」「代码一跑就掉坑」的同学。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;TCP/IP 不是一门「背完就能会」的技术。它由一整套分层协议组成，每一层只关心自己的事情，又通过严格定义的头部把信息交给下一层。理解这套分层思维，是看懂网络报文、写出稳定网络程序、排查线上连接问题的第一步。&lt;/p&gt;
&lt;p&gt;这篇文章不会把所有 RFC 都讲一遍（那是 1000 多页书做的事），而是帮你建立&lt;strong&gt;主干知识框架&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TCP/IP 协议栈为什么要分层？数据是怎么一层层包起来的？&lt;/li&gt;
&lt;li&gt;IP、TCP、UDP、ARP、ICMP、DNS 这些协议各自解决什么问题？&lt;/li&gt;
&lt;li&gt;Unix Socket 编程的核心 API 与调用顺序是什么？&lt;/li&gt;
&lt;li&gt;写网络程序最容易踩哪些坑，怎么避开？&lt;/li&gt;
&lt;li&gt;遇到连接失败、卡顿、端口耗尽这些问题，该按什么思路排查？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;读完之后，你应该能看懂 Wireshark 里的大部分常见报文，也能独立写出稳定的 TCP 客户端/服务端，并具备基础的线上网络问题排查能力。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一tcpip-协议栈为什么必须分层&#34;&gt;一、TCP/IP 协议栈：为什么必须分层？&lt;/h2&gt;
&lt;p&gt;网络通信的复杂度非常高：不同的物理介质、不同的操作系统、不同的应用程序要在全球范围内交换数据。如果不分层，每一台设备都要同时处理「电信号怎么传」「数据怎么路由」「传输可不可靠」「应用数据什么意思」所有问题。&lt;/p&gt;
&lt;p&gt;分层的目的就是&lt;strong&gt;关注点分离&lt;/strong&gt;：每一层只解决本层的问题，向上层提供服务，把复杂问题拆成可管理的小块。&lt;/p&gt;
&lt;h3 id=&#34;11-osi-七层模型-vs-tcpip-四层模型&#34;&gt;1.1 OSI 七层模型 vs TCP/IP 四层模型&lt;/h3&gt;
&lt;p&gt;教学中常用 OSI 七层模型，但互联网实际运行的是 TCP/IP 四层模型。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    subgraph OSI七层模型
        A7[7 应用层] --&amp;gt; A6[6 表示层]
        A6 --&amp;gt; A5[5 会话层]
        A5 --&amp;gt; A4[4 传输层]
        A4 --&amp;gt; A3[3 网络层]
        A3 --&amp;gt; A2[2 数据链路层]
        A2 --&amp;gt; A1[1 物理层]
    end

    subgraph TCP/IP四层模型
        B4[应用层&amp;lt;br/&amp;gt;HTTP/FTP/DNS/SMTP] --&amp;gt; B3[传输层&amp;lt;br/&amp;gt;TCP/UDP]
        B3 --&amp;gt; B2[网络层&amp;lt;br/&amp;gt;IP/ICMP/IGMP]
        B2 --&amp;gt; B1[网络接口层&amp;lt;br/&amp;gt;以太网/WiFi/PPP]
    end

    A7 -.对应.-&amp;gt; B4
    A6 -.对应.-&amp;gt; B4
    A5 -.对应.-&amp;gt; B4
    A4 -.对应.-&amp;gt; B3
    A3 -.对应.-&amp;gt; B2
    A2 -.对应.-&amp;gt; B1
    A1 -.对应.-&amp;gt; B1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;TCP/IP 层&lt;/th&gt;
					&lt;th&gt;核心协议&lt;/th&gt;
					&lt;th&gt;解决的问题&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;应用层&lt;/td&gt;
					&lt;td&gt;HTTP、DNS、FTP、SMTP、SSH&lt;/td&gt;
					&lt;td&gt;应用程序之间「说什么」&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;传输层&lt;/td&gt;
					&lt;td&gt;TCP、UDP&lt;/td&gt;
					&lt;td&gt;进程到进程的通信，可靠或高效传输&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;网络层&lt;/td&gt;
					&lt;td&gt;IP、ICMP、IGMP、路由协议&lt;/td&gt;
					&lt;td&gt;主机到主机的寻址与路由&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;网络接口层&lt;/td&gt;
					&lt;td&gt;以太网、WiFi、ARP、PPP&lt;/td&gt;
					&lt;td&gt;相邻设备之间的物理/逻辑传输&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;新手容易混淆的点&lt;/strong&gt;：TCP/IP 里的「应用层」实际上对应了 OSI 的应用层、表示层、会话层三层。不要死磕七层，实际工程里四层模型更常用。&lt;/p&gt;
&lt;h3 id=&#34;12-数据封装与解封装&#34;&gt;1.2 数据封装与解封装&lt;/h3&gt;
&lt;p&gt;每一层都会给上一层的数据加一个「头部」，然后交给下一层。接收方则逐层去掉头部，把数据交给上层。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    subgraph 发送方
        A[应用数据] --&amp;gt;|&amp;#34;应用层封装&amp;#34;| B[&amp;#34;应用层头部 + 应用数据&amp;#34;]
        B --&amp;gt;|&amp;#34;传输层封装&amp;#34;| C[&amp;#34;TCP/UDP 头部 + 应用层数据&amp;#34;]
        C --&amp;gt;|&amp;#34;网络层封装&amp;#34;| D[&amp;#34;IP 头部 + TCP 数据段&amp;#34;]
        D --&amp;gt;|&amp;#34;链路层封装&amp;#34;| E[&amp;#34;以太网头部 + IP 数据报 + 以太网尾部&amp;#34;]
    end

    E --&amp;gt;|&amp;#34;比特流在物理介质传输&amp;#34;| F

    subgraph 接收方
        F[&amp;#34;以太网帧&amp;#34;] --&amp;gt;|&amp;#34;链路层解封装&amp;#34;| G[&amp;#34;IP 数据报&amp;#34;]
        G --&amp;gt;|&amp;#34;网络层解封装&amp;#34;| H[&amp;#34;TCP/UDP 数据段&amp;#34;]
        H --&amp;gt;|&amp;#34;传输层解封装&amp;#34;| I[&amp;#34;应用层数据&amp;#34;]
        I --&amp;gt;|&amp;#34;应用层处理&amp;#34;| J[交给对应进程]
    end&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键概念&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MTU（Maximum Transmission Unit）&lt;/strong&gt;：链路层帧能承载的最大数据量，以太网常见值是 1500 字节。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MSS（Maximum Segment Size）&lt;/strong&gt;：TCP 一次能发送的最大数据段，通常 = MTU - IP 头 - TCP 头，以太网常见 1460 字节。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分片（Fragmentation）&lt;/strong&gt;：当 IP 数据报超过链路 MTU 时，IP 层会把它切成多个片。TCP 一般会通过 MSS 避免分片，UDP 则容易触发分片。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要随意修改 MTU，VPN/隧道场景特别容易出现「大数据包被静默丢弃」的问题。&lt;/li&gt;
&lt;li&gt;UDP 应用如果要传输大报文，建议在应用层自己拆包，不要让 IP 层分片。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二链路层与-arp同一局域网怎么找到对方&#34;&gt;二、链路层与 ARP：同一局域网怎么找到对方？&lt;/h2&gt;
&lt;p&gt;链路层负责&lt;strong&gt;相邻节点&lt;/strong&gt;之间的数据传输。在以太网里，设备用 MAC 地址标识，交换机根据 MAC 地址转发帧。&lt;/p&gt;
&lt;h3 id=&#34;21-以太网帧结构&#34;&gt;2.1 以太网帧结构&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+----------------+----------------+----------------+----------------+----------------+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| 目的 MAC 6B    | 源 MAC 6B      | 类型 2B        | 数据 46~1500B  | FCS 4B         |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+----------------+----------------+----------------+----------------+----------------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MAC 地址&lt;/strong&gt;：48 位，全球唯一（理论上），用于局域网内定位网卡。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型字段&lt;/strong&gt;：例如 &lt;code&gt;0x0800&lt;/code&gt; 表示上层是 IP，&lt;code&gt;0x0806&lt;/code&gt; 表示 ARP。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FCS（Frame Check Sequence）&lt;/strong&gt;：帧校验序列，检测传输过程中的比特错误。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;22-arpip-地址--mac-地址&#34;&gt;2.2 ARP：IP 地址 → MAC 地址&lt;/h3&gt;
&lt;p&gt;ARP（Address Resolution Protocol）解决的是「知道对方 IP，但不知道对方 MAC」的问题。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant A as 主机 A&amp;lt;br/&amp;gt;192.168.1.10
    participant B as 主机 B&amp;lt;br/&amp;gt;192.168.1.20

    A-&amp;gt;&amp;gt;B: ARP 请求：谁的 IP 是 192.168.1.20？请告诉我你的 MAC
    Note over A,B: 广播帧，局域网内所有主机收到
    B-&amp;gt;&amp;gt;A: ARP 应答：我是 192.168.1.20，MAC 是 xx:xx:xx:xx:xx:xx
    Note over A,B: 单播帧，只有 A 收到&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;ARP 表会缓存一段时间：&lt;code&gt;arp -a&lt;/code&gt; 可以查看本机 ARP 缓存。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ARP 只在&lt;strong&gt;同一二层网络&lt;/strong&gt;（同一广播域）有效。跨网段通信时，主机把报文发给网关，由网关继续转发。&lt;/li&gt;
&lt;li&gt;网关配错是新手常见问题：如果默认网关不在同一子网，ARP 请求会失败，数据根本发不出去。&lt;/li&gt;
&lt;li&gt;ARP 欺骗/中间人攻击在局域网内存在，敏感环境要开启动态 ARP 检测（DAI）或静态绑定。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三ip-协议主机到主机的寻址与路由&#34;&gt;三、IP 协议：主机到主机的寻址与路由&lt;/h2&gt;
&lt;p&gt;IP（Internet Protocol）是网络层的核心，负责把数据从源主机送到目的主机。它&lt;strong&gt;不保证可靠、不保证有序&lt;/strong&gt;，这些由 TCP 或应用层自己处理。&lt;/p&gt;
&lt;h3 id=&#34;31-ipv4-头部核心字段&#34;&gt;3.1 IPv4 头部核心字段&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 0                   1                   2                   3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|Version|  IHL  |Type of Service|          Total Length         |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|         Identification        |Flags|      Fragment Offset    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  Time to Live |    Protocol   |         Header Checksum       |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                       Source Address                          |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                    Destination Address                        |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                    Options                    |    Padding    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;关键字段含义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version&lt;/strong&gt;：IPv4 填 4，IPv6 填 6。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IHL（Header Length）&lt;/strong&gt;：头部长度，单位是 4 字节。没有选项时最小是 5，即 20 字节。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total Length&lt;/strong&gt;：整个 IP 数据报的长度，最大 65535 字节。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identification / Flags / Fragment Offset&lt;/strong&gt;：用于分片和重组。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TTL（Time to Live）&lt;/strong&gt;：每经过一个路由器减 1，到 0 被丢弃，防止报文在网络里无限循环。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protocol&lt;/strong&gt;：上层协议类型。6 = TCP，17 = UDP，1 = ICMP，等等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Source/Destination Address&lt;/strong&gt;：源 IP 和目的 IP。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;32-ip-地址子网掩码与-cidr&#34;&gt;3.2 IP 地址、子网掩码与 CIDR&lt;/h3&gt;
&lt;p&gt;IP 地址 = 网络号 + 主机号。子网掩码用来划分这两部分。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IP 地址：    192.168.1.100   → 11000000.10101000.00000001.01100100
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;子网掩码：   255.255.255.0   → 11111111.11111111.11111111.00000000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;网络号：     192.168.1.0     → 前 24 位
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;主机号：     0.0.0.100       → 后 8 位&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;CIDR 表示法：&lt;code&gt;192.168.1.0/24&lt;/code&gt;，斜杠后面的数字表示网络号位数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;判断两台主机是否在同一子网&lt;/strong&gt;：用各自的 IP 和子网掩码做按位与，得到网络号，网络号相同就在同一子网。&lt;/p&gt;
&lt;h3 id=&#34;33-路由基础&#34;&gt;3.3 路由基础&lt;/h3&gt;
&lt;p&gt;当目的 IP 不在本子网时，主机会把报文发给&lt;strong&gt;默认网关&lt;/strong&gt;（Default Gateway）。路由器根据路由表决定下一跳。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[主机 A&amp;lt;br/&amp;gt;192.168.1.10/24] --&amp;gt;|&amp;#34;目的 IP 不在同一子网&amp;#34;| R[路由器&amp;lt;br/&amp;gt;192.168.1.1]
    R --&amp;gt;|&amp;#34;查路由表&amp;#34;| B[主机 B&amp;lt;br/&amp;gt;10.0.0.5/24]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;常用查看命令：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Linux/macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ip route show        &lt;span style=&#34;color:#75715e&#34;&gt;# 查看路由表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;route -n             &lt;span style=&#34;color:#75715e&#34;&gt;# 旧命令&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;route print&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置静态 IP 时，最容易漏掉或配错的就是&lt;strong&gt;子网掩码&lt;/strong&gt;和&lt;strong&gt;默认网关&lt;/strong&gt;。只配 IP 不配上两者，通常只能 ping 通同网段。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/24&lt;/code&gt; 和 &lt;code&gt;/16&lt;/code&gt; 的区别不只是数字大小，它决定了网络规模和可用主机数。&lt;code&gt;/24&lt;/code&gt; 有 254 个可用主机地址，&lt;code&gt;/16&lt;/code&gt; 有 65534 个。&lt;/li&gt;
&lt;li&gt;路由表顺序很重要：更具体的子网（前缀更长）优先于默认路由。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四icmpip-的诊断助手&#34;&gt;四、ICMP：IP 的「诊断助手」&lt;/h2&gt;
&lt;p&gt;ICMP（Internet Control Message Protocol）本身不传输用户数据，而是用于&lt;strong&gt;传递控制消息和诊断信息&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;41-ping-原理&#34;&gt;4.1 Ping 原理&lt;/h3&gt;
&lt;p&gt;Ping 使用 ICMP Echo Request 和 Echo Reply。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant A as 主机 A
    participant B as 主机 B

    A-&amp;gt;&amp;gt;B: ICMP Echo Request
    Note over A,B: 携带标识符和序列号
    B-&amp;gt;&amp;gt;A: ICMP Echo Reply
    Note over A,B: A 根据往返时间计算延迟&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;Ping 不通不一定是对端关机，可能是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;防火墙拦截了 ICMP&lt;/li&gt;
&lt;li&gt;路由不可达&lt;/li&gt;
&lt;li&gt;对端 ARP 表异常&lt;/li&gt;
&lt;li&gt;本机默认网关配错&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;42-traceroute-原理&#34;&gt;4.2 Traceroute 原理&lt;/h3&gt;
&lt;p&gt;Traceroute 利用 TTL 递增或端口不可达来追踪路径。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[主机] --&amp;gt;|&amp;#34;TTL=1&amp;#34;| R1[路由器 1]
    R1 --&amp;gt;|&amp;#34;TTL 超时，返回 ICMP Time Exceeded&amp;#34;| A
    A --&amp;gt;|&amp;#34;TTL=2&amp;#34;| R2[路由器 2]
    R2 --&amp;gt;|&amp;#34;TTL 超时，返回 ICMP Time Exceeded&amp;#34;| A
    A --&amp;gt;|&amp;#34;TTL=3&amp;#34;| B[目标主机]
    B --&amp;gt;|&amp;#34;端口不可达 / Echo Reply&amp;#34;| A&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有些路由器配置了「不回应 ICMP Time Exceeded」，Traceroute 会显示 &lt;code&gt;* * *&lt;/code&gt;，不代表网络不通。&lt;/li&gt;
&lt;li&gt;防火墙可能会阻断 Traceroute 的 UDP 探测端口，换 &lt;code&gt;-I&lt;/code&gt;（ICMP）或 &lt;code&gt;-T&lt;/code&gt;（TCP）模式可能成功。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五udp简单高效不可靠&#34;&gt;五、UDP：简单、高效、不可靠&lt;/h2&gt;
&lt;p&gt;UDP（User Datagram Protocol）提供&lt;strong&gt;无连接、不可靠、面向数据报&lt;/strong&gt;的传输服务。&lt;/p&gt;
&lt;h3 id=&#34;51-udp-头部&#34;&gt;5.1 UDP 头部&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 0      7 8     15 16    23 24    31
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+--------+--------+--------+--------+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|     Source Port    |   Dest Port   |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+--------+--------+--------+--------+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|     Length         |   Checksum    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+--------+--------+--------+--------+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|          data octets ...            |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-------------------------------------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source Port / Dest Port&lt;/strong&gt;：各 16 位，标识发送和接收进程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Length&lt;/strong&gt;：UDP 头部 + 数据的总长度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Checksum&lt;/strong&gt;：可选（IPv4 中），覆盖头部、数据和伪头部。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;52-udp-的特点与适用场景&#34;&gt;5.2 UDP 的特点与适用场景&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特点&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;无连接&lt;/td&gt;
					&lt;td&gt;不需要建立连接，直接发&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;不可靠&lt;/td&gt;
					&lt;td&gt;不保证到达、不保证顺序、不重传&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;低开销&lt;/td&gt;
					&lt;td&gt;头部只有 8 字节&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;面向数据报&lt;/td&gt;
					&lt;td&gt;发一次收一次，保留边界&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;适合用 UDP 的场景&lt;/strong&gt;：DNS 查询、视频直播、在线游戏、VoIP、NTP、QUIC 底层。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UDP 没有流量控制，发送方太快会导致接收方丢包。实时音视频要做抖动缓冲（jitter buffer）和前向纠错（FEC）。&lt;/li&gt;
&lt;li&gt;UDP 报文超过 MTU 会被 IP 层分片，分片丢失会导致整个 UDP 报文作废。大数据包要在应用层分片。&lt;/li&gt;
&lt;li&gt;不要认为 UDP 一定比 TCP 快。在丢包率高的网络里，应用层自己实现可靠传输可能比 TCP 更复杂且效果更差。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六tcp可靠传输的基石&#34;&gt;六、TCP：可靠传输的基石&lt;/h2&gt;
&lt;p&gt;TCP（Transmission Control Protocol）是互联网最常用的传输协议。它提供&lt;strong&gt;面向连接、可靠、按序、字节流&lt;/strong&gt;的服务。&lt;/p&gt;
&lt;h3 id=&#34;61-tcp-头部核心字段&#34;&gt;6.1 TCP 头部核心字段&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 0                   1                   2                   3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|          Source Port          |       Destination Port        |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                        Sequence Number                        |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                    Acknowledgment Number                      |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|  Data |           |U|A|P|R|S|F|                               |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|       |           |G|K|H|T|N|N|                               |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|           Checksum            |         Urgent Pointer        |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                    Options                    |    Padding    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;关键字段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sequence Number（序号）&lt;/strong&gt;：标识本报文段发送的数据在字节流中的位置。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Acknowledgment Number（确认号）&lt;/strong&gt;：期望收到的下一个字节的序号。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ACK&lt;/strong&gt;：确认号有效。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SYN&lt;/strong&gt;：发起连接。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FIN&lt;/strong&gt;：结束连接。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RST&lt;/strong&gt;：重置连接，通常表示异常。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Window（窗口大小）&lt;/strong&gt;：接收方当前可用缓存大小，用于流量控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;62-三次握手建立连接&#34;&gt;6.2 三次握手：建立连接&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant C as 客户端
    participant S as 服务端

    C-&amp;gt;&amp;gt;S: SYN, seq=x
    Note over C,S: 客户端请求建立连接
    S-&amp;gt;&amp;gt;C: SYN, seq=y, ACK=x+1
    Note over C,S: 服务端同意，也请求建立反向连接
    C-&amp;gt;&amp;gt;S: ACK=y+1
    Note over C,S: 客户端确认，连接建立&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么是三次？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;两次握手无法确认客户端的接收能力，也不能防止历史重复连接请求造成资源浪费。&lt;/li&gt;
&lt;li&gt;三次是「双方都能发送和接收」的最小验证次数。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;关键状态&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户端：SYN_SENT → ESTABLISHED&lt;/li&gt;
&lt;li&gt;服务端：LISTEN → SYN_RCVD → ESTABLISHED&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;63-四次挥手关闭连接&#34;&gt;6.3 四次挥手：关闭连接&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant C as 客户端
    participant S as 服务端

    C-&amp;gt;&amp;gt;S: FIN, seq=u
    Note over C,S: 客户端没有数据要发了
    S-&amp;gt;&amp;gt;C: ACK=u+1
    Note over C,S: 服务端确认，但可能还有数据要发
    S-&amp;gt;&amp;gt;C: FIN, seq=w
    Note over C,S: 服务端也没有数据要发了
    C-&amp;gt;&amp;gt;S: ACK=w+1
    Note over C,S: 客户端确认&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么一般是四次？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;TCP 是全双工的，两个方向要分别关闭。一方发完 FIN 只表示「我这方向没数据了」，另一方可能还有数据要发。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关键状态与时间等待&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主动关闭方最后进入 &lt;strong&gt;TIME_WAIT&lt;/strong&gt;，等待 2MSL（Maximum Segment Lifetime，通常 1-4 分钟）后才彻底关闭。&lt;/li&gt;
&lt;li&gt;TIME_WAIT 的作用：
&lt;ol&gt;
&lt;li&gt;确保最后一个 ACK 被对方收到，如果丢失可以重传。&lt;/li&gt;
&lt;li&gt;让网络中延迟的报文自然消失，避免影响下一个使用相同四元组的新连接。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;64-tcp-状态机&#34;&gt;6.4 TCP 状态机&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;stateDiagram-v2
    [*] --&amp;gt; CLOSED
    CLOSED --&amp;gt; SYN_SENT : 主动打开/send SYN
    CLOSED --&amp;gt; LISTEN : 被动打开
    SYN_SENT --&amp;gt; ESTABLISHED : 收到 SYN+ACK
    LISTEN --&amp;gt; SYN_RCVD : 收到 SYN
    SYN_RCVD --&amp;gt; ESTABLISHED : 收到 ACK
    ESTABLISHED --&amp;gt; FIN_WAIT_1 : 主动关闭/send FIN
    ESTABLISHED --&amp;gt; CLOSE_WAIT : 收到 FIN
    FIN_WAIT_1 --&amp;gt; FIN_WAIT_2 : 收到 ACK
    FIN_WAIT_1 --&amp;gt; TIME_WAIT : 收到 FIN+ACK
    FIN_WAIT_2 --&amp;gt; TIME_WAIT : 收到 FIN
    CLOSE_WAIT --&amp;gt; LAST_ACK : 发送 FIN
    LAST_ACK --&amp;gt; CLOSED : 收到 ACK
    TIME_WAIT --&amp;gt; CLOSED : 2MSL 超时&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;65-可靠传输机制&#34;&gt;6.5 可靠传输机制&lt;/h3&gt;
&lt;p&gt;TCP 通过以下机制保证可靠性：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[序号与确认机制] --&amp;gt; B[超时重传]
    C[滑动窗口] --&amp;gt; D[流量控制]
    E[拥塞窗口] --&amp;gt; F[拥塞控制]
    B --&amp;gt; G[可靠传输]
    D --&amp;gt; G
    F --&amp;gt; G&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;序号与确认&lt;/strong&gt;：每发一个字节都有序号，接收方用 ACK 确认连续收到的最大序号。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;超时重传&lt;/strong&gt;：发送方启动定时器，超时未收到 ACK 就重传。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;滑动窗口&lt;/strong&gt;：允许发送方在没收到 ACK 的情况下连续发送多个段，提高吞吐量。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;流量控制&lt;/strong&gt;：接收方通过 Window 字段告诉发送方自己还能接收多少数据，防止接收方缓存溢出。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;拥塞控制&lt;/strong&gt;：发送方根据网络拥塞程度调整发送速率，主要算法包括慢启动、拥塞避免、快重传、快恢复。&lt;/p&gt;
&lt;h3 id=&#34;66-拥塞控制四个阶段&#34;&gt;6.6 拥塞控制四个阶段&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[慢启动&amp;lt;br/&amp;gt;cwnd 指数增长] --&amp;gt;|&amp;#34;cwnd &amp;gt;= ssthresh&amp;#34;| B[拥塞避免&amp;lt;br/&amp;gt;cwnd 线性增长]
    B --&amp;gt;|&amp;#34;收到 3 个重复 ACK&amp;#34;| C[快重传&amp;lt;br/&amp;gt;立即重传]
    C --&amp;gt; D[快恢复&amp;lt;br/&amp;gt;cwnd=ssthresh]
    D --&amp;gt; B
    B --&amp;gt;|&amp;#34;超时&amp;#34;| E[超时重传&amp;lt;br/&amp;gt;cwnd=1]
    E --&amp;gt; A&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;慢启动（Slow Start）&lt;/strong&gt;：初始窗口小，每收到一个 ACK 窗口近似翻倍，直到达到慢启动阈值（ssthresh）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;拥塞避免（Congestion Avoidance）&lt;/strong&gt;：超过阈值后，窗口线性增长。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快重传（Fast Retransmit）&lt;/strong&gt;：收到 3 个重复 ACK 就立刻重传，不等超时。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快恢复（Fast Recovery）&lt;/strong&gt;：快重传后不把窗口降到 1，而是降到 ssthresh，再线性增长。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;67-nagle-算法与延迟-ack&#34;&gt;6.7 Nagle 算法与延迟 ACK&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nagle 算法&lt;/strong&gt;：减少小报文数量。如果上一次发送的数据还没被确认，且当前数据量小于 MSS，就把小数据攒起来一起发。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;延迟 ACK&lt;/strong&gt;：接收方不立即对每个收到的段发 ACK，而是等 40ms 左右，看是否有数据要一起回，减少 ACK 数量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nagle + 延迟 ACK 会造成明显延迟&lt;/strong&gt;：发送方等小 ACK，接收方等大数据一起回，形成「写 - 等 - 写 - 等」的 ping-pong 效应。&lt;/li&gt;
&lt;li&gt;交互式应用（如游戏、SSH、RPC）通常要关闭 Nagle：&lt;code&gt;setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &amp;amp;on, sizeof(on))&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;批量传输场景（文件下载）可以保留 Nagle，减少小包数量。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七dns-与-dhcp网络配置的基础设施&#34;&gt;七、DNS 与 DHCP：网络配置的基础设施&lt;/h2&gt;
&lt;h3 id=&#34;71-dns域名--ip&#34;&gt;7.1 DNS：域名 → IP&lt;/h3&gt;
&lt;p&gt;DNS（Domain Name System）是互联网的「电话簿」，把人类可读的域名解析成 IP 地址。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[客户端] --&amp;gt;|&amp;#34;查询 example.com&amp;#34;| B[本地 DNS 缓存]
    B --&amp;gt;|&amp;#34;未命中&amp;#34;| C[递归 DNS 服务器]
    C --&amp;gt;|&amp;#34;迭代查询&amp;#34;| D[根 DNS 服务器]
    D --&amp;gt; E[.com 顶级域服务器]
    E --&amp;gt; F[example.com 权威服务器]
    F --&amp;gt;|&amp;#34;返回 IP&amp;#34;| C
    C --&amp;gt;|&amp;#34;返回 IP&amp;#34;| A&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;DNS 记录类型&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;类型&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;A&lt;/td&gt;
					&lt;td&gt;域名 → IPv4 地址&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;AAAA&lt;/td&gt;
					&lt;td&gt;域名 → IPv6 地址&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CNAME&lt;/td&gt;
					&lt;td&gt;域名别名&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;MX&lt;/td&gt;
					&lt;td&gt;邮件交换服务器&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;NS&lt;/td&gt;
					&lt;td&gt;权威 DNS 服务器&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TXT&lt;/td&gt;
					&lt;td&gt;文本记录，常用于验证和 SPF&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DNS 有缓存，修改记录后全球生效可能要几分钟到 48 小时（受 TTL 控制）。&lt;/li&gt;
&lt;li&gt;注意 DNS 解析失败和连接超时的区别：先 &lt;code&gt;nslookup&lt;/code&gt;/&lt;code&gt;dig&lt;/code&gt; 确认域名能否解析，再 ping/telnet 确认网络层是否通。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gethostbyname&lt;/code&gt; 不是线程安全的，现代程序应使用 &lt;code&gt;getaddrinfo&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;72-dhcp自动获取网络配置&#34;&gt;7.2 DHCP：自动获取网络配置&lt;/h3&gt;
&lt;p&gt;DHCP（Dynamic Host Configuration Protocol）让主机自动获取 IP 地址、子网掩码、网关、DNS 服务器。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant H as 主机
    participant D as DHCP 服务器

    H-&amp;gt;&amp;gt;D: DHCP Discover（广播）
    D-&amp;gt;&amp;gt;H: DHCP Offer
    H-&amp;gt;&amp;gt;D: DHCP Request
    D-&amp;gt;&amp;gt;H: DHCP ACK&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;八unix-网络编程核心socket-api&#34;&gt;八、Unix 网络编程核心：Socket API&lt;/h2&gt;
&lt;p&gt;Socket 是 Unix 系统提供的网络编程接口，屏蔽了底层协议细节，让程序像读写文件一样通信。&lt;/p&gt;
&lt;h3 id=&#34;81-tcp-服务端典型调用流程&#34;&gt;8.1 TCP 服务端典型调用流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[socket] --&amp;gt; B[bind]
    B --&amp;gt; C[listen]
    C --&amp;gt; D[accept]
    D --&amp;gt; E[read/write]
    E --&amp;gt; F[close]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;82-tcp-客户端典型调用流程&#34;&gt;8.2 TCP 客户端典型调用流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[socket] --&amp;gt; B[connect]
    B --&amp;gt; C[read/write]
    C --&amp;gt; D[close]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;83-核心-api-说明&#34;&gt;8.3 核心 API 说明&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;API&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;socket()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;创建套接字，指定协议族（IPv4/IPv6）和类型（流式/数据报）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;bind()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;把套接字绑定到本地地址和端口&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;listen()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;把套接字置为监听状态，指定全连接队列长度&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;accept()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;从全连接队列取出一个已完成握手的连接&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;connect()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;客户端发起连接&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;read()/write()&lt;/code&gt; 或 &lt;code&gt;recv()/send()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;收发数据&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;关闭连接&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;shutdown()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;半关闭：只关闭读或写&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;84-最简-tcp-服务端示例&#34;&gt;8.4 最简 TCP 服务端示例&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define PORT 8080
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define BACKLOG 128
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; listen_fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;socket&lt;/span&gt;(AF_INET, SOCK_STREAM, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (listen_fd &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;socket&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; reuse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;setsockopt&lt;/span&gt;(listen_fd, SOL_SOCKET, SO_REUSEADDR, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;reuse, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(reuse));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr_in addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;memset&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;addr, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(addr));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addr.sin_family &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AF_INET;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addr.sin_addr.s_addr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; INADDR_ANY;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addr.sin_port &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htons&lt;/span&gt;(PORT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;bind&lt;/span&gt;(listen_fd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;addr, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(addr)) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bind&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;listen&lt;/span&gt;(listen_fd, BACKLOG) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;listen&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Server listening on port %d&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, PORT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr_in client_addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;socklen_t&lt;/span&gt; len &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(client_addr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; conn_fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;accept&lt;/span&gt;(listen_fd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;client_addr, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (conn_fd &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;accept&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; buf[&lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;ssize_t&lt;/span&gt; n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;read&lt;/span&gt;(conn_fd, buf, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(buf) &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (n &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            buf[n] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Received: %s&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, buf);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(conn_fd, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OK&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(conn_fd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(listen_fd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;85-最简-tcp-客户端示例&#34;&gt;8.5 最简 TCP 客户端示例&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define SERVER &amp;#34;127.0.0.1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define PORT 8080
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;socket&lt;/span&gt;(AF_INET, SOCK_STREAM, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (fd &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;socket&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr_in addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;memset&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;addr, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(addr));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addr.sin_family &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AF_INET;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addr.sin_port &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htons&lt;/span&gt;(PORT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;inet_pton&lt;/span&gt;(AF_INET, SERVER, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;addr.sin_addr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;connect&lt;/span&gt;(fd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;addr, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(addr)) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;perror&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;connect&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(fd, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; buf[&lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;ssize_t&lt;/span&gt; n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;read&lt;/span&gt;(fd, buf, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(buf) &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (n &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        buf[n] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Server reply: %s&amp;#34;&lt;/span&gt;, buf);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(fd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;九unix-网络编程常见陷阱与避坑技巧&#34;&gt;九、Unix 网络编程常见陷阱与避坑技巧&lt;/h2&gt;
&lt;h3 id=&#34;91-必须设置-so_reuseaddr&#34;&gt;9.1 必须设置 SO_REUSEADDR&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; reuse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;setsockopt&lt;/span&gt;(listen_fd, SOL_SOCKET, SO_REUSEADDR, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;reuse, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(reuse));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：服务端主动关闭连接后会进入 TIME_WAIT，该连接的本地端口短时间内不能复用。如果不设置 SO_REUSEADDR，重启服务时可能报 &lt;code&gt;Address already in use&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：SO_REUSEADDR 允许复用 TIME_WAIT 的端口，但不会允许两个进程同时绑定到完全相同的 &lt;code&gt;IP:端口&lt;/code&gt;（Linux 上 SO_REUSEPORT 才能做到）。&lt;/p&gt;
&lt;h3 id=&#34;92-正确处理-sigpipe&#34;&gt;9.2 正确处理 SIGPIPE&lt;/h3&gt;
&lt;p&gt;向一个已经收到 RST 的 socket 写数据会触发 &lt;code&gt;SIGPIPE&lt;/code&gt; 信号，默认行为是终止进程。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;signal&lt;/span&gt;(SIGPIPE, SIG_IGN);  &lt;span style=&#34;color:#75715e&#34;&gt;// 忽略信号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;更优雅的做法是在写之前检查连接状态，或者使用 &lt;code&gt;MSG_NOSIGNAL&lt;/code&gt; 标志：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send&lt;/span&gt;(fd, buf, len, MSG_NOSIGNAL);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;93-处理部分读写&#34;&gt;9.3 处理部分读写&lt;/h3&gt;
&lt;p&gt;TCP 是字节流，&lt;code&gt;read&lt;/code&gt; 和 &lt;code&gt;write&lt;/code&gt; 不保证一次读完或写完。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 可靠的写：循环写直到写完
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ssize_t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;write_all&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; fd, &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;buf, &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; len) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; buf;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; remaining &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (remaining &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;ssize_t&lt;/span&gt; n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(fd, p, remaining);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (n &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (errno &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; EINTR) &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        p &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; n;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        remaining &lt;span style=&#34;color:#f92672&#34;&gt;-=&lt;/span&gt; n;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;94-处理-eintr&#34;&gt;9.4 处理 EINTR&lt;/h3&gt;
&lt;p&gt;慢系统调用（如 &lt;code&gt;accept&lt;/code&gt;、&lt;code&gt;read&lt;/code&gt;、&lt;code&gt;write&lt;/code&gt;）被信号中断后会返回 -1 并设置 &lt;code&gt;errno = EINTR&lt;/code&gt;。 robust 的程序应该重试：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; ((n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;read&lt;/span&gt;(fd, buf, len)) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; errno &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; EINTR)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;95-不要用-strlen-计算二进制数据长度&#34;&gt;9.5 不要用 strlen 计算二进制数据长度&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;send(fd, buf, strlen(buf), 0)&lt;/code&gt; 只适合文本。二进制数据里可能有 &lt;code&gt;\0&lt;/code&gt;，要用实际长度。&lt;/p&gt;
&lt;h3 id=&#34;96-使用-getaddrinfo-替代-gethostbyname&#34;&gt;9.6 使用 getaddrinfo 替代 gethostbyname&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;gethostbyname&lt;/code&gt; 只支持 IPv4，不是线程安全的，已经被废弃。现代程序应使用 &lt;code&gt;getaddrinfo&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; addrinfo hints, &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;res;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;memset&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;hints, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(hints));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hints.ai_family &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AF_UNSPEC;      &lt;span style=&#34;color:#75715e&#34;&gt;// 支持 IPv4 和 IPv6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hints.ai_socktype &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; SOCK_STREAM;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; err &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getaddrinfo&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;example.com&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;80&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;hints, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;res);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (err &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fprintf&lt;/span&gt;(stderr, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;getaddrinfo: %s&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;gai_strerror&lt;/span&gt;(err));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;exit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;socket&lt;/span&gt;(res&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;ai_family, res&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;ai_socktype, res&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;ai_protocol);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;connect&lt;/span&gt;(fd, res&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;ai_addr, res&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;ai_addrlen);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;freeaddrinfo&lt;/span&gt;(res);  &lt;span style=&#34;color:#75715e&#34;&gt;// 记得释放
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;97-区分-close-与-shutdown&#34;&gt;9.7 区分 close 与 shutdown&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;close(fd)&lt;/code&gt;：关闭文件描述符，引用计数减到 0 时释放资源，双向关闭。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shutdown(fd, SHUT_WR)&lt;/code&gt;：只关闭写方向，读仍然可以接收数据，常用于通知对端「我发完了」。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;98-阻塞-vs-非阻塞-io&#34;&gt;9.8 阻塞 vs 非阻塞 IO&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;模式&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;阻塞&lt;/td&gt;
					&lt;td&gt;调用没完成就挂起&lt;/td&gt;
					&lt;td&gt;简单程序、每个连接一个线程/进程&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;非阻塞&lt;/td&gt;
					&lt;td&gt;调用立即返回，没数据返回 EAGAIN/EWOULDBLOCK&lt;/td&gt;
					&lt;td&gt;高并发、IO 多路复用&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;99-io-多路复用&#34;&gt;9.9 IO 多路复用&lt;/h3&gt;
&lt;p&gt;单线程服务大量连接时，要用 IO 多路复用同时监视多个 fd 的就绪状态。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[主线程] --&amp;gt; B[select/poll/epoll]
    B --&amp;gt;|&amp;#34;哪些 fd 可读/可写&amp;#34;| C[处理可读 fd]
    B --&amp;gt; D[处理可写 fd]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;机制&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;select&lt;/td&gt;
					&lt;td&gt;有 fd 数量限制（通常 1024），每次调用要遍历全部 fd&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;poll&lt;/td&gt;
					&lt;td&gt;用数组描述 fd，没有数量硬限制，但仍需遍历&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;epoll（Linux）&lt;/td&gt;
					&lt;td&gt;事件驱动，只关注活跃的 fd，支持边缘触发和水平触发&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;kqueue（BSD/macOS）&lt;/td&gt;
					&lt;td&gt;类似 epoll，事件驱动&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;epoll 水平触发（LT）vs 边缘触发（ET）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LT：只要 fd 还有数据可读，epoll 就会一直通知。&lt;/li&gt;
&lt;li&gt;ET：只有 fd 状态变化时通知一次，需要一次性把数据读完，通常配合非阻塞 IO。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十典型-unix-网络障碍问题与排查思路&#34;&gt;十、典型 Unix 网络障碍问题与排查思路&lt;/h2&gt;
&lt;h3 id=&#34;101-排查流程总览&#34;&gt;10.1 排查流程总览&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[网络问题] --&amp;gt; B[确认是 DNS/路由/端口/应用哪一层]
    B --&amp;gt; C{能解析域名吗?}
    C --&amp;gt;|否| D[检查 DNS / hosts / 防火墙]
    C --&amp;gt;|是| E{能 ping 通 IP 吗?}
    E --&amp;gt;|否| F[检查路由 / ACL / 安全组]
    E --&amp;gt;|是| G{端口通吗?}
    G --&amp;gt;|否| H[检查服务是否监听 / 防火墙 / 安全组]
    G --&amp;gt;|是| I[检查应用日志 / 抓包 / 连接状态]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;102-connection-refused&#34;&gt;10.2 Connection refused&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：目标 IP 可达，但目标端口没有进程在监听，或者防火墙明确拒绝。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;排查&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 服务端检查是否在监听&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ss -tlnp | grep &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;netstat -tlnp | grep &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 客户端测试端口是否开放&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;telnet server_ip &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nc -vz server_ip &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;103-connection-timed-out&#34;&gt;10.3 Connection timed out&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：报文到达目的地过程中被丢弃，没有收到任何 RST 或响应，常见于防火墙静默丢弃、路由不可达、NAT 映射问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;排查&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 看路径到哪里断了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;traceroute server_ip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mtr server_ip
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 抓包看 SYN 有没有出去、有没有回来&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tcpdump -i any port &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt; -nn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;104-too-many-time_wait--端口耗尽&#34;&gt;10.4 Too many TIME_WAIT / 端口耗尽&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：高并发短连接场景下，客户端连接失败，报错 &lt;code&gt;Cannot assign requested address&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：大量主动关闭的连接堆积在 TIME_WAIT，占用了本地端口。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决思路&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;尽量使用长连接 / 连接池。&lt;/li&gt;
&lt;li&gt;服务端设置 &lt;code&gt;SO_REUSEADDR&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Linux 可调整 &lt;code&gt;net.ipv4.ip_local_port_range&lt;/code&gt; 扩大临时端口范围。&lt;/li&gt;
&lt;li&gt;开启 &lt;code&gt;net.ipv4.tcp_tw_reuse&lt;/code&gt;（谨慎，仅对客户端出站连接有效，不要开 &lt;code&gt;tcp_tw_recycle&lt;/code&gt;，已在内核 4.12 后移除）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;105-close_wait-堆积&#34;&gt;10.5 CLOSE_WAIT 堆积&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：服务端 &lt;code&gt;ss -tan | grep CLOSE_WAIT&lt;/code&gt; 看到很多连接。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：对端已经发了 FIN，但本端应用没有调用 &lt;code&gt;close()&lt;/code&gt;，通常是因为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用逻辑忘记关闭 socket。&lt;/li&gt;
&lt;li&gt;应用在处理完数据前阻塞在某处，无法执行 close。&lt;/li&gt;
&lt;li&gt;异常分支没有释放连接资源。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：检查代码里所有异常路径是否都调用了 &lt;code&gt;close&lt;/code&gt;，确保每个 &lt;code&gt;accept&lt;/code&gt; 出来的 fd 都有对应的关闭点。&lt;/p&gt;
&lt;h3 id=&#34;106-syn-flood--半连接队列溢出&#34;&gt;10.6 SYN Flood / 半连接队列溢出&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：服务偶尔出现连接建立慢或大量 &lt;code&gt;SYN_SENT&lt;/code&gt;/&lt;code&gt;SYN_RECV&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;：Linux 内核有两个队列：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;半连接队列（syn queue）&lt;/strong&gt;：存放收到 SYN 但还没完成三次握手的连接。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全连接队列（accept queue）&lt;/strong&gt;：存放已完成三次握手但还没被 &lt;code&gt;accept&lt;/code&gt; 取走的连接。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[客户端 SYN] --&amp;gt;|&amp;#34;进入半连接队列&amp;#34;| B[SYN_RCVD]
    B --&amp;gt;|&amp;#34;收到 ACK&amp;#34;| C[ESTABLISHED]
    C --&amp;gt;|&amp;#34;进入全连接队列&amp;#34;| D[等待 accept]
    D --&amp;gt;|&amp;#34;accept 取走&amp;#34;| E[交给业务处理]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;排查&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ss -s          &lt;span style=&#34;color:#75715e&#34;&gt;# 查看连接统计&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ss -lnt        &lt;span style=&#34;color:#75715e&#34;&gt;# 看全连接队列长度和溢出次数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;netstat -s | grep overflow&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;调大 &lt;code&gt;net.ipv4.tcp_max_syn_backlog&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;开启 SYN Cookies：&lt;code&gt;net.ipv4.tcp_syncookies = 1&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;增大 &lt;code&gt;listen(fd, backlog)&lt;/code&gt; 的 backlog，同时配合 &lt;code&gt;somaxconn&lt;/code&gt; 调整。&lt;/li&gt;
&lt;li&gt;提升应用 &lt;code&gt;accept&lt;/code&gt; 速度。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;107-高并发下-accept-慢或全连接队列溢出&#34;&gt;10.7 高并发下 accept 慢或全连接队列溢出&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：连接完成三次握手，但客户端一直等待服务端响应。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：&lt;code&gt;accept&lt;/code&gt; 处理太慢，全连接队列满了，新的完成连接被丢弃。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用多线程/多进程分担 accept。&lt;/li&gt;
&lt;li&gt;使用 IO 多路复用 + 事件驱动架构。&lt;/li&gt;
&lt;li&gt;调整 &lt;code&gt;net.core.somaxconn&lt;/code&gt; 和 &lt;code&gt;listen()&lt;/code&gt; 的 backlog。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;108-mtumss-导致的大包不通&#34;&gt;10.8 MTU/MSS 导致的大包不通&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：小数据包能通，大数据包不通；或某些网站/服务能打开，某些打不开。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：路径中某段链路 MTU 较小，大包被丢弃，且中间设备不发送 ICMP &amp;ldquo;Fragmentation Needed&amp;rdquo;，导致无法自动降包大小。这就是著名的 &lt;strong&gt;PMTUD（Path MTU Discovery）黑洞&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;设置 &lt;code&gt;net.ipv4.tcp_mtu_probing = 1&lt;/code&gt; 启用 TCP MTU 探测。&lt;/li&gt;
&lt;li&gt;在 VPN/隧道两端统一调低 MTU/MSS。&lt;/li&gt;
&lt;li&gt;中间网络设备不要丢弃 ICMP &amp;ldquo;Fragmentation Needed&amp;rdquo;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;109-应用层协议粘包拆包&#34;&gt;10.9 应用层协议粘包/拆包&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：TCP 客户端发了两条消息，服务端一次 read 读到了两条消息的内容。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：TCP 是字节流，没有消息边界。应用层需要自己定义消息边界。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常见解决方案&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;固定长度&lt;/strong&gt;：每个消息固定 N 字节。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分隔符&lt;/strong&gt;：如 &lt;code&gt;\n&lt;/code&gt;、自定义分隔符。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长度前缀&lt;/strong&gt;：消息头 4 字节表示消息体长度。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 长度前缀示例：先读 4 字节长度，再读对应长度的 body
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;read_all&lt;/span&gt;(fd, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;len, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;len &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ntohl&lt;/span&gt;(len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;read_all&lt;/span&gt;(fd, body, len);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;十一学习路线与推荐资源&#34;&gt;十一、学习路线与推荐资源&lt;/h2&gt;
&lt;h3 id=&#34;111-学习顺序建议&#34;&gt;11.1 学习顺序建议&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[网络分层模型] --&amp;gt; B[IP/子网/路由]
    B --&amp;gt; C[ARP/ICMP]
    C --&amp;gt; D[TCP 握手挥手与状态机]
    D --&amp;gt; E[滑动窗口与拥塞控制]
    E --&amp;gt; F[Socket API 编程]
    F --&amp;gt; G[IO 多路复用]
    G --&amp;gt; H[Wireshark 抓包分析]
    H --&amp;gt; I[线上问题排查]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;112-推荐实践&#34;&gt;11.2 推荐实践&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;用 Wireshark 抓一次完整的三次握手和四次挥手&lt;/strong&gt;，亲眼看看每个字段的值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写一个 echo 服务器&lt;/strong&gt;，先用阻塞 IO，再用 select/epoll 改写。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;故意制造问题&lt;/strong&gt;：把客户端改成快速创建大量短连接，观察 TIME_WAIT；把服务端 accept 故意睡几秒，观察全连接队列溢出。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用 &lt;code&gt;ss&lt;/code&gt;、&lt;code&gt;tcpdump&lt;/code&gt;、&lt;code&gt;traceroute&lt;/code&gt;、&lt;code&gt;nc&lt;/code&gt;、&lt;code&gt;iperf&lt;/code&gt; 这些工具做实验&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;113-推荐参考书&#34;&gt;11.3 推荐参考书&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;《TCP/IP 详解 卷1：协议》（W. Richard Stevens）——协议细节最权威。&lt;/li&gt;
&lt;li&gt;《Unix 网络编程 卷1：套接字联网 API》（W. Richard Stevens）——Socket 编程圣经。&lt;/li&gt;
&lt;li&gt;《Wireshark 网络分析就这么简单》——抓包实战。&lt;/li&gt;
&lt;li&gt;《Linux 高性能服务器编程》（游双）——中文入门友好。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十二总结&#34;&gt;十二、总结&lt;/h2&gt;
&lt;p&gt;TCP/IP 协议栈并不神秘，它的核心思想就是&lt;strong&gt;分层与解耦&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;链路层负责「相邻设备怎么传」。&lt;/li&gt;
&lt;li&gt;网络层负责「怎么找到对方主机」。&lt;/li&gt;
&lt;li&gt;传输层负责「怎么把数据交给正确的进程，并决定可靠还是高效」。&lt;/li&gt;
&lt;li&gt;应用层负责「这些数据代表什么业务含义」。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unix 网络编程的核心是理解 Socket API 的调用顺序、IO 模型、以及 TCP 连接的生命周期。写出稳定的网络程序，不在于记住所有参数，而在于理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;连接是什么时候建立的，什么时候关闭的。&lt;/li&gt;
&lt;li&gt;数据是怎么流动的，会不会被截断、会不会粘包。&lt;/li&gt;
&lt;li&gt;异常情况下系统会怎么表现，程序能不能正确处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;希望这份总结能帮你把《TCP/IP 详解》里的知识点串成一张网，少踩一些网络编程里的经典大坑。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
