哈喽,编程搭子们!😜 又到了沉浸式敲代码的快乐时间~把生活调成「代码模式」,带着满满的热爱钻进编程的奇妙世界------今天也要敲出超酷的代码,冲鸭!🚀

✨ 我的博客主页:喜欢吃燃面
📚 我的专栏(持续更新ing):
《C语言》 |
《C语言之数据结构》 |
《C++》 |
《Linux学习笔记》
💖 超感谢你点开这篇博客!真心希望这些内容能帮到正在打怪升级的你~如果有任何想法、疑问,或者想交流学习心得,都欢迎留言/私信,咱们一起在编程路上互相陪伴、共同进步呀!
引言:为什么需要网络协议
在计算机科学领域,网络通信是现代信息技术的基石。当我们发送一条消息、浏览一个网页或传输一份文件时,数据究竟是如何从一台设备准确无误地到达另一台设备的?这背后涉及的操作系统机制、协议分层设计以及数据封装与解封装过程,构成了网络编程的核心知识体系。本文将基于网络协议的本质,深入剖析从底层硬件到上层应用的数据传输全过程,帮助读者建立完整的网络通信认知框架。
网络协议本质上是一种"约定"。在计算机世界中,任何两个实体要进行有效通信,都必须事先约定好通信规则。这种约定包括数据格式、传输顺序、错误处理机制等。正如人类交流需要共同的语言一样,计算机之间的通信也需要统一的"语言"------这就是协议。协议的存在解决了异构系统之间的互联互通问题,使得不同厂商、不同操作系统、不同硬件架构的设备能够无缝协作。
一、协议的分层思想
1.1 分层结构的必要性
网络通信面临的核心问题可以归纳为以下几点:网络通信面临的核心问题可以归纳为以下几点:
a. 数据如何在两个相隔甚远的设备之间传输?
物理距离是网络通信首先要克服的障碍。数据需要跨越局域网、城域网、广域网,甚至跨越海洋和大洲,才能到达目的地。这个过程中涉及信号衰减、噪声干扰、路由选择等一系列复杂问题。物理距离是网络通信首先要克服的障碍。数据需要跨越局域网、城域网、广域网,甚至跨越海洋和大洲,才能到达目的地。这个过程中涉及信号衰减、噪声干扰、路由选择等一系列复杂问题。
b. 目标主机定位和路径选择的问题
互联网上连接着数十亿台设备,如何准确找到目标主机?数据包在传输过程中需要经过无数路由器和交换机,如何选择最优路径?这些问题需要精巧的寻址和路由机制来解决。互联网上连接着数十亿台设备,如何准确找到目标主机?数据包在传输过程中需要经过无数路由器和交换机,如何选择最优路径?这些问题需要精巧的寻址和路由机制来解决。
c. 数据丢失和损坏的情况如何处理?
物理链路并非完美无缺,数据包可能在传输过程中丢失、损坏或乱序。如何检测这些错误?如何确保数据的完整性和有序性?这需要可靠的传输机制。物理链路并非完美无缺,数据包可能在传输过程中丢失、损坏或乱序。如何检测这些错误?如何确保数据的完整性和有序性?这需要可靠的传输机制。
d. 数据到达后的目的和处理方式
即使数据成功到达目标主机,操作系统还需要知道将数据交给哪个进程处理。一台主机上可能同时运行着浏览器、邮件客户端、视频播放器等多个网络应用,如何区分它们的数据?即使数据成功到达目标主机,操作系统还需要知道将数据交给哪个进程处理。一台主机上可能同时运行着浏览器、邮件客户端、视频播放器等多个网络应用,如何区分它们的数据?
1.2 TCP/IP协议栈的分层设计
为了解决上述问题,网络协议采用了分层设计的思想。TCP/IP 协议栈将网络通信划分为四个层次:
#mermaid-svg-BcDYDSVW9JP8lzgu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BcDYDSVW9JP8lzgu .error-icon{fill:#552222;}#mermaid-svg-BcDYDSVW9JP8lzgu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BcDYDSVW9JP8lzgu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BcDYDSVW9JP8lzgu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BcDYDSVW9JP8lzgu .marker.cross{stroke:#333333;}#mermaid-svg-BcDYDSVW9JP8lzgu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BcDYDSVW9JP8lzgu p{margin:0;}#mermaid-svg-BcDYDSVW9JP8lzgu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu .cluster-label text{fill:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu .cluster-label span{color:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu .cluster-label span p{background-color:transparent;}#mermaid-svg-BcDYDSVW9JP8lzgu .label text,#mermaid-svg-BcDYDSVW9JP8lzgu span{fill:#333;color:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu .node rect,#mermaid-svg-BcDYDSVW9JP8lzgu .node circle,#mermaid-svg-BcDYDSVW9JP8lzgu .node ellipse,#mermaid-svg-BcDYDSVW9JP8lzgu .node polygon,#mermaid-svg-BcDYDSVW9JP8lzgu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BcDYDSVW9JP8lzgu .rough-node .label text,#mermaid-svg-BcDYDSVW9JP8lzgu .node .label text,#mermaid-svg-BcDYDSVW9JP8lzgu .image-shape .label,#mermaid-svg-BcDYDSVW9JP8lzgu .icon-shape .label{text-anchor:middle;}#mermaid-svg-BcDYDSVW9JP8lzgu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BcDYDSVW9JP8lzgu .rough-node .label,#mermaid-svg-BcDYDSVW9JP8lzgu .node .label,#mermaid-svg-BcDYDSVW9JP8lzgu .image-shape .label,#mermaid-svg-BcDYDSVW9JP8lzgu .icon-shape .label{text-align:center;}#mermaid-svg-BcDYDSVW9JP8lzgu .node.clickable{cursor:pointer;}#mermaid-svg-BcDYDSVW9JP8lzgu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BcDYDSVW9JP8lzgu .arrowheadPath{fill:#333333;}#mermaid-svg-BcDYDSVW9JP8lzgu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BcDYDSVW9JP8lzgu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BcDYDSVW9JP8lzgu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BcDYDSVW9JP8lzgu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BcDYDSVW9JP8lzgu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BcDYDSVW9JP8lzgu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BcDYDSVW9JP8lzgu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BcDYDSVW9JP8lzgu .cluster text{fill:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu .cluster span{color:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BcDYDSVW9JP8lzgu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BcDYDSVW9JP8lzgu rect.text{fill:none;stroke-width:0;}#mermaid-svg-BcDYDSVW9JP8lzgu .icon-shape,#mermaid-svg-BcDYDSVW9JP8lzgu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BcDYDSVW9JP8lzgu .icon-shape p,#mermaid-svg-BcDYDSVW9JP8lzgu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BcDYDSVW9JP8lzgu .icon-shape .label rect,#mermaid-svg-BcDYDSVW9JP8lzgu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BcDYDSVW9JP8lzgu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BcDYDSVW9JP8lzgu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BcDYDSVW9JP8lzgu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TCP/IP 协议栈
应用层
HTTP, FTP, SMTP, DNS
传输层
TCP, UDP
网络层
IP, ICMP, ARP
数据链路层
以太网, WiFi, PPP
物理层
光纤, 双绞线, 无线电波
应用层负责为应用程序提供网络服务接口,常见的协议包括 HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(简单邮件传输协议)、DNS(域名系统)等。应用层协议直接面向用户需求,定义了数据的语义和交互逻辑。应用层负责为应用程序提供网络服务接口,常见的协议包括 HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(简单邮件传输协议)、DNS(域名系统)等。应用层协议直接面向用户需求,定义了数据的语义和交互逻辑。
传输层负责端到端的可靠数据传输。TCP(传输控制协议)提供面向连接的、可靠的字节流服务,通过三次握手建立连接、四次挥手断开连接,并通过确认应答、超时重传、流量控制、拥塞控制等机制保证数据可靠性。UDP(用户数据报协议)则提供无连接的、尽最大努力交付的数据报服务,适用于实时性要求高但可容忍少量丢包的场景。传输层负责端到端的可靠数据传输。TCP(传输控制协议)提供面向连接的、可靠的字节流服务,通过三次握手建立连接、四次挥手断开连接,并通过确认应答、超时重传、流量控制、拥塞控制等机制保证数据可靠性。UDP(用户数据报协议)则提供无连接的、尽最大努力交付的数据报服务,适用于实时性要求高但可容忍少量丢包的场景。
网络层负责数据包从源主机到目的主机的路由选择和转发。IP(网际协议)是网络层的核心,它定义了 IP 地址格式、数据包格式以及路由算法。ICMP(互联网控制消息协议)用于传递控制消息和错误报告。ARP(地址解析协议)用于将 IP 地址解析为 MAC 地址。网络层负责数据包从源主机到目的主机的路由选择和转发。IP(网际协议)是网络层的核心,它定义了 IP 地址格式、数据包格式以及路由算法。ICMP(互联网控制消息协议)用于传递控制消息和错误报告。ARP(地址解析协议)用于将 IP 地址解析为 MAC 地址。
数据链路层负责相邻节点之间的数据传输。以太网是最常见的数据链路层技术,它定义了帧格式、MAC 地址以及 CSMA/CD(载波侦听多路访问/冲突检测)机制。WiFi(无线局域网)也是数据链路层的重要技术。数据链路层负责相邻节点之间的数据传输。以太网是最常见的数据链路层技术,它定义了帧格式、MAC 地址以及 CSMA/CD(载波侦听多路访问/冲突检测)机制。WiFi(无线局域网)也是数据链路层的重要技术。
1.3 分层设计的优势
分层设计带来了诸多好处:
独立性:每一层只需要关注自己的职责,不需要了解其他层的实现细节。层与层之间通过定义良好的接口交互。
灵活性:某一层的技术升级或替换不会影响其他层。例如,物理层可以从双绞线升级为光纤,而应用层完全无感知。
标准化:分层使得不同厂商可以独立开发各层产品,只要遵循相同的接口规范,就能实现互联互通。
二、网络传输的基本流程
2.1 局域网通信
局域网(LAN)是覆盖范围较小的网络,通常局限于一个建筑物或校园内。在局域网中,每台主机都需要有唯一的标识来确保数据能够准确送达。局域网(LAN)是覆盖范围较小的网络,通常局限于一个建筑物或校园内。在局域网中,每台主机都需要有唯一的标识来确保数据能够准确送达。
MAC 地址是数据链路层的物理地址,由 48 位二进制数组成,通常表示为 6 组十六进制数(如 00:16:3e:10:cc:36)。MAC 地址在网卡出厂时固化,全球唯一。通过 ifconfig 或 ip addr 命令可以查看本机的 MAC 地址和网络配置信息。
局域网通信的核心问题是:主机 A 如何找到主机 B?
在以太网中,数据以帧的形式传输。每个以太网帧包含源 MAC 地址和目的 MAC 地址。当主机 A 要向主机 B 发送数据时,它会将数据封装成帧,并在帧头中填入主机 B 的 MAC 地址。然后,这个帧被发送到共享的物理介质上,局域网中的所有主机都能收到这个帧,但只有 MAC 地址匹配的主机 B 会接收并处理它,其他主机则丢弃该帧。
这种工作方式引出了冲突检测问题。当多台主机同时发送数据时,信号会在物理介质上发生冲突,导致数据损坏。以太网采用 CSMA/CD(载波侦听多路访问/冲突检测) 机制来解决这个问题:
发送前先监听信道是否空闲;
如果空闲则发送数据;
发送过程中持续检测是否发生冲突;
如果检测到冲突,立即停止发送,发送干扰信号,等待随机时间后重试。
主机C 主机B 共享总线 主机A 主机C 主机B 共享总线 主机A #mermaid-svg-Bsjlqb1373Qfet72{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Bsjlqb1373Qfet72 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Bsjlqb1373Qfet72 .error-icon{fill:#552222;}#mermaid-svg-Bsjlqb1373Qfet72 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Bsjlqb1373Qfet72 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Bsjlqb1373Qfet72 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Bsjlqb1373Qfet72 .marker.cross{stroke:#333333;}#mermaid-svg-Bsjlqb1373Qfet72 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Bsjlqb1373Qfet72 p{margin:0;}#mermaid-svg-Bsjlqb1373Qfet72 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Bsjlqb1373Qfet72 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Bsjlqb1373Qfet72 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Bsjlqb1373Qfet72 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Bsjlqb1373Qfet72 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Bsjlqb1373Qfet72 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Bsjlqb1373Qfet72 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Bsjlqb1373Qfet72 .sequenceNumber{fill:white;}#mermaid-svg-Bsjlqb1373Qfet72 #sequencenumber{fill:#333;}#mermaid-svg-Bsjlqb1373Qfet72 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Bsjlqb1373Qfet72 .messageText{fill:#333;stroke:none;}#mermaid-svg-Bsjlqb1373Qfet72 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Bsjlqb1373Qfet72 .labelText,#mermaid-svg-Bsjlqb1373Qfet72 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Bsjlqb1373Qfet72 .loopText,#mermaid-svg-Bsjlqb1373Qfet72 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Bsjlqb1373Qfet72 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Bsjlqb1373Qfet72 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Bsjlqb1373Qfet72 .noteText,#mermaid-svg-Bsjlqb1373Qfet72 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Bsjlqb1373Qfet72 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Bsjlqb1373Qfet72 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Bsjlqb1373Qfet72 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Bsjlqb1373Qfet72 .actorPopupMenu{position:absolute;}#mermaid-svg-Bsjlqb1373Qfet72 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Bsjlqb1373Qfet72 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Bsjlqb1373Qfet72 .actor-man circle,#mermaid-svg-Bsjlqb1373Qfet72 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Bsjlqb1373Qfet72 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 发送数据帧(目的MAC=B) 转发数据帧 转发数据帧 检查MAC地址匹配,接收数据 检查MAC地址不匹配,丢弃数据
2.2 跨网络通信
当通信双方不在同一个局域网时,就需要跨网络传输。当通信双方不在同一个局域网时,就需要跨网络传输。这时,仅靠MAC地址已经不够了,因为MAC地址只在局域网内有效,无法用于广域网路由。
IP地址应运而生。IP地址应运而生。IP地址是网络层的逻辑地址,用于在互联网中唯一标识一台主机。IPv4 地址由32位二进制数组成,通常表示为4个十进制数(如192.168.1.1)。IP地址分为网络号和主机号两部分,通过子网掩码来划分。
跨网络通信的核心机制是路由。跨网络通信的核心机制是路由。当数据需要从一个网络传输到另一个网络时,需要经过路由器的转发。路由器是连接不同网络的设备,它维护着路由表,根据目的IP地址决定数据包的下一跳。
#mermaid-svg-iVLBxnYezBmu7Ouk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iVLBxnYezBmu7Ouk .error-icon{fill:#552222;}#mermaid-svg-iVLBxnYezBmu7Ouk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iVLBxnYezBmu7Ouk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iVLBxnYezBmu7Ouk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iVLBxnYezBmu7Ouk .marker.cross{stroke:#333333;}#mermaid-svg-iVLBxnYezBmu7Ouk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iVLBxnYezBmu7Ouk p{margin:0;}#mermaid-svg-iVLBxnYezBmu7Ouk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk .cluster-label text{fill:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk .cluster-label span{color:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk .cluster-label span p{background-color:transparent;}#mermaid-svg-iVLBxnYezBmu7Ouk .label text,#mermaid-svg-iVLBxnYezBmu7Ouk span{fill:#333;color:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk .node rect,#mermaid-svg-iVLBxnYezBmu7Ouk .node circle,#mermaid-svg-iVLBxnYezBmu7Ouk .node ellipse,#mermaid-svg-iVLBxnYezBmu7Ouk .node polygon,#mermaid-svg-iVLBxnYezBmu7Ouk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iVLBxnYezBmu7Ouk .rough-node .label text,#mermaid-svg-iVLBxnYezBmu7Ouk .node .label text,#mermaid-svg-iVLBxnYezBmu7Ouk .image-shape .label,#mermaid-svg-iVLBxnYezBmu7Ouk .icon-shape .label{text-anchor:middle;}#mermaid-svg-iVLBxnYezBmu7Ouk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iVLBxnYezBmu7Ouk .rough-node .label,#mermaid-svg-iVLBxnYezBmu7Ouk .node .label,#mermaid-svg-iVLBxnYezBmu7Ouk .image-shape .label,#mermaid-svg-iVLBxnYezBmu7Ouk .icon-shape .label{text-align:center;}#mermaid-svg-iVLBxnYezBmu7Ouk .node.clickable{cursor:pointer;}#mermaid-svg-iVLBxnYezBmu7Ouk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iVLBxnYezBmu7Ouk .arrowheadPath{fill:#333333;}#mermaid-svg-iVLBxnYezBmu7Ouk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iVLBxnYezBmu7Ouk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iVLBxnYezBmu7Ouk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iVLBxnYezBmu7Ouk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iVLBxnYezBmu7Ouk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iVLBxnYezBmu7Ouk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iVLBxnYezBmu7Ouk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iVLBxnYezBmu7Ouk .cluster text{fill:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk .cluster span{color:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iVLBxnYezBmu7Ouk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iVLBxnYezBmu7Ouk rect.text{fill:none;stroke-width:0;}#mermaid-svg-iVLBxnYezBmu7Ouk .icon-shape,#mermaid-svg-iVLBxnYezBmu7Ouk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iVLBxnYezBmu7Ouk .icon-shape p,#mermaid-svg-iVLBxnYezBmu7Ouk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iVLBxnYezBmu7Ouk .icon-shape .label rect,#mermaid-svg-iVLBxnYezBmu7Ouk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iVLBxnYezBmu7Ouk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iVLBxnYezBmu7Ouk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iVLBxnYezBmu7Ouk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 局域网B
互联网
局域网A
数据包
数据包
主机A
192.168.1.10
路由器1
路由器2
路由器3
主机B
10.0.0.20
2.3 封装与解封装
数据在传输过程中会经历封装和解封装的过程。数据在传输过程中会经历封装和解封装的过程。发送方从应用层开始,逐层向下添加头部信息;接收方则从物理层开始,逐层向上剥离头部信息,最终提取出原始数据。
#mermaid-svg-bie7OfkmBMpAjWLT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bie7OfkmBMpAjWLT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bie7OfkmBMpAjWLT .error-icon{fill:#552222;}#mermaid-svg-bie7OfkmBMpAjWLT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bie7OfkmBMpAjWLT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bie7OfkmBMpAjWLT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bie7OfkmBMpAjWLT .marker.cross{stroke:#333333;}#mermaid-svg-bie7OfkmBMpAjWLT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bie7OfkmBMpAjWLT p{margin:0;}#mermaid-svg-bie7OfkmBMpAjWLT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bie7OfkmBMpAjWLT .cluster-label text{fill:#333;}#mermaid-svg-bie7OfkmBMpAjWLT .cluster-label span{color:#333;}#mermaid-svg-bie7OfkmBMpAjWLT .cluster-label span p{background-color:transparent;}#mermaid-svg-bie7OfkmBMpAjWLT .label text,#mermaid-svg-bie7OfkmBMpAjWLT span{fill:#333;color:#333;}#mermaid-svg-bie7OfkmBMpAjWLT .node rect,#mermaid-svg-bie7OfkmBMpAjWLT .node circle,#mermaid-svg-bie7OfkmBMpAjWLT .node ellipse,#mermaid-svg-bie7OfkmBMpAjWLT .node polygon,#mermaid-svg-bie7OfkmBMpAjWLT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bie7OfkmBMpAjWLT .rough-node .label text,#mermaid-svg-bie7OfkmBMpAjWLT .node .label text,#mermaid-svg-bie7OfkmBMpAjWLT .image-shape .label,#mermaid-svg-bie7OfkmBMpAjWLT .icon-shape .label{text-anchor:middle;}#mermaid-svg-bie7OfkmBMpAjWLT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bie7OfkmBMpAjWLT .rough-node .label,#mermaid-svg-bie7OfkmBMpAjWLT .node .label,#mermaid-svg-bie7OfkmBMpAjWLT .image-shape .label,#mermaid-svg-bie7OfkmBMpAjWLT .icon-shape .label{text-align:center;}#mermaid-svg-bie7OfkmBMpAjWLT .node.clickable{cursor:pointer;}#mermaid-svg-bie7OfkmBMpAjWLT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bie7OfkmBMpAjWLT .arrowheadPath{fill:#333333;}#mermaid-svg-bie7OfkmBMpAjWLT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bie7OfkmBMpAjWLT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bie7OfkmBMpAjWLT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bie7OfkmBMpAjWLT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bie7OfkmBMpAjWLT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bie7OfkmBMpAjWLT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bie7OfkmBMpAjWLT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bie7OfkmBMpAjWLT .cluster text{fill:#333;}#mermaid-svg-bie7OfkmBMpAjWLT .cluster span{color:#333;}#mermaid-svg-bie7OfkmBMpAjWLT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bie7OfkmBMpAjWLT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bie7OfkmBMpAjWLT rect.text{fill:none;stroke-width:0;}#mermaid-svg-bie7OfkmBMpAjWLT .icon-shape,#mermaid-svg-bie7OfkmBMpAjWLT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bie7OfkmBMpAjWLT .icon-shape p,#mermaid-svg-bie7OfkmBMpAjWLT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bie7OfkmBMpAjWLT .icon-shape .label rect,#mermaid-svg-bie7OfkmBMpAjWLT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bie7OfkmBMpAjWLT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bie7OfkmBMpAjWLT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bie7OfkmBMpAjWLT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接收方_解封装过程
发送方_封装过程
传输介质
应用层数据
添加TCP/UDP头部
传输层数据段
添加IP头部
网络层数据包
添加MAC头部
数据链路层帧
物理层比特流
物理层比特流
剥离MAC头部
数据链路层帧
剥离IP头部
网络层数据包
剥离TCP/UDP头部
传输层数据段
应用层数据
每一层的头部都包含该层协议所需的关键信息:每一层的头部都包含该层协议所需的关键信息:
TCP/UDP 头部:包含源端口号、目的端口号、序列号、确认号、窗口大小等
IP 头部:包含源 IP 地址、目的 IP 地址、TTL(生存时间)、协议类型等
MAC 头部:包含源 MAC 地址、目的 MAC 地址、类型字段等
这种封装机制使得每一层都能独立处理自己的协议信息,而不需要关心其他层的内容。同时,头部信息就像快递单上的地址标签,确保数据能够准确到达目的地。这种封装机制使得每一层都能独立处理自己的协议信息,而不需要关心其他层的内容。同时,头部信息就像快递单上的地址标签,确保数据能够准确到达目的地。
三、IP 地址与端口号
3.1 IP地址的作用
IP 地址是网络层的核心概念,它解决了"数据从哪里来,到哪里去"的问题。IP 地址的主要作用包括:
标识网络中的唯一主机:在全球互联网中,每个公网 IP 地址都是唯一的(不考虑 NAT 的情况),它就像每台主机的"门牌号"。
路由选择的依据:路由器根据目的 IP 地址查询路由表,决定数据包的转发路径。IP 地址的网络号部分用于确定目标网络,主机号部分用于确定网络内的具体主机。
网络分层的基础:IP 地址支持子网划分,使得大型网络可以被划分为多个小型子网,提高网络管理效率。
3.2 端口号的引入
当数据包到达目标主机后,操作系统面临一个新的问题:应该将数据交给哪个进程处理?一台主机上可能同时运行着多个网络应用程序,如 Web 浏览器(使用 HTTP 协议)、邮件客户端(使用 SMTP/POP3 协议)、FTP 客户端等。它们都通过网络收发数据,操作系统如何区分这些数据属于哪个应用?
端口号就是解决这个问题的关键。端口号是一个16位的整数,范围从0到65535。它用于标识主机上的特定网络进程。不同的网络服务使用不同的知名端口号:

知名端口(0-1023):由 IANA 统一分配,用于常见的网络服务,需要管理员权限才能绑定。
注册端口(1024-49151):用于用户注册的应用程序服务,普通用户可以使用。
动态/私有端口(49152-65535):临时分配给客户端程序使用,通信结束后释放。
3.3 四元组:唯一标识一个通信连接
在互联网中,一个完整的网络通信由四元组唯一标识:
{源IP地址, 源端口号, 目的IP地址, 目的端口号}
例如,当主机 A(IP: 192.168.1.10)上的浏览器(端口: 8888)访问主机 B(IP: 167.182.3.45)上的 Web 服务器(端口: 9999)时,这个通信连接可以表示为:
{192.168.1.10, 8888, 167.182.3.45, 9999}
四元组确保了即使在同一台主机上,不同的应用程序也能独立地进行网络通信而不会相互干扰。操作系统内核维护着一张套接字表,根据四元组将接收到的数据分发给对应的进程。
#mermaid-svg-iM8KzSGIdWGwZJDk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iM8KzSGIdWGwZJDk .error-icon{fill:#552222;}#mermaid-svg-iM8KzSGIdWGwZJDk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iM8KzSGIdWGwZJDk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iM8KzSGIdWGwZJDk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iM8KzSGIdWGwZJDk .marker.cross{stroke:#333333;}#mermaid-svg-iM8KzSGIdWGwZJDk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iM8KzSGIdWGwZJDk p{margin:0;}#mermaid-svg-iM8KzSGIdWGwZJDk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk .cluster-label text{fill:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk .cluster-label span{color:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk .cluster-label span p{background-color:transparent;}#mermaid-svg-iM8KzSGIdWGwZJDk .label text,#mermaid-svg-iM8KzSGIdWGwZJDk span{fill:#333;color:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk .node rect,#mermaid-svg-iM8KzSGIdWGwZJDk .node circle,#mermaid-svg-iM8KzSGIdWGwZJDk .node ellipse,#mermaid-svg-iM8KzSGIdWGwZJDk .node polygon,#mermaid-svg-iM8KzSGIdWGwZJDk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iM8KzSGIdWGwZJDk .rough-node .label text,#mermaid-svg-iM8KzSGIdWGwZJDk .node .label text,#mermaid-svg-iM8KzSGIdWGwZJDk .image-shape .label,#mermaid-svg-iM8KzSGIdWGwZJDk .icon-shape .label{text-anchor:middle;}#mermaid-svg-iM8KzSGIdWGwZJDk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iM8KzSGIdWGwZJDk .rough-node .label,#mermaid-svg-iM8KzSGIdWGwZJDk .node .label,#mermaid-svg-iM8KzSGIdWGwZJDk .image-shape .label,#mermaid-svg-iM8KzSGIdWGwZJDk .icon-shape .label{text-align:center;}#mermaid-svg-iM8KzSGIdWGwZJDk .node.clickable{cursor:pointer;}#mermaid-svg-iM8KzSGIdWGwZJDk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iM8KzSGIdWGwZJDk .arrowheadPath{fill:#333333;}#mermaid-svg-iM8KzSGIdWGwZJDk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iM8KzSGIdWGwZJDk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iM8KzSGIdWGwZJDk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iM8KzSGIdWGwZJDk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iM8KzSGIdWGwZJDk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iM8KzSGIdWGwZJDk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iM8KzSGIdWGwZJDk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iM8KzSGIdWGwZJDk .cluster text{fill:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk .cluster span{color:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iM8KzSGIdWGwZJDk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iM8KzSGIdWGwZJDk rect.text{fill:none;stroke-width:0;}#mermaid-svg-iM8KzSGIdWGwZJDk .icon-shape,#mermaid-svg-iM8KzSGIdWGwZJDk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iM8KzSGIdWGwZJDk .icon-shape p,#mermaid-svg-iM8KzSGIdWGwZJDk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iM8KzSGIdWGwZJDk .icon-shape .label rect,#mermaid-svg-iM8KzSGIdWGwZJDk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iM8KzSGIdWGwZJDk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iM8KzSGIdWGwZJDk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iM8KzSGIdWGwZJDk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 主机B
网络
主机A
{192.168.1.10,8888,167.182.3.45,9999}
{192.168.1.10,4321,某IP,某端口}
{192.168.1.10,10086,某IP,某端口}
浏览器进程
端口: 8888
QQ进程
端口: 4321
邮件客户端
端口: 10086
互联网
Web服务器
端口: 9999
四、Socket:网络通信的编程接口
4.1 Socket的本质
Socket(套接字)是操作系统提供的网络编程接口,它封装了TCP/IP 协议的复杂性,为应用程序提供了简洁的网络通信能力。从操作系统内核的角度看,Socket本质上是一个struct file 结构体------在Linux系统中,一切皆文件,网络连接也不例外。
Socket具有以下核心属性:
协议族:指定使用的协议类型,如AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNIX(本地通信)等。
套接字类型:指定通信语义,如SOCK_STREAM(面向连接的流式套接字,对应 TCP)、SOCK_DGRAM(无连接的数据报套接字,对应 UDP)。
协议:指定具体的传输协议,如IPPROTO_TCP、IPPROTO_UDP 等。
本地地址和端口:绑定到套接字的本地IP地址和端口号。
远程地址和端口(对于已连接的套接字):通信对端的IP地址和端口号。
发送缓冲区和接收缓冲区:用于暂存待发送和已接收的数据。
状态信息:描述套接字当前的状态,如监听、已连接、关闭等。
4.2 Socket的工作流程
TCP Socket 的通信流程如下:
服务器端:
创建Socket(socket())
绑定地址和端口(bind())
监听连接请求(listen())
接受客户端连接(accept())
收发数据(send()/recv())
关闭连接(close())
客户端:
创建Socket(socket())
连接服务器(connect())
收发数据(send()/recv())
关闭连接(close())
服务器 客户端 服务器 客户端 #mermaid-svg-bxHPVzUj3gI5BwA6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bxHPVzUj3gI5BwA6 .error-icon{fill:#552222;}#mermaid-svg-bxHPVzUj3gI5BwA6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bxHPVzUj3gI5BwA6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bxHPVzUj3gI5BwA6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bxHPVzUj3gI5BwA6 .marker.cross{stroke:#333333;}#mermaid-svg-bxHPVzUj3gI5BwA6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bxHPVzUj3gI5BwA6 p{margin:0;}#mermaid-svg-bxHPVzUj3gI5BwA6 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bxHPVzUj3gI5BwA6 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-bxHPVzUj3gI5BwA6 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-bxHPVzUj3gI5BwA6 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-bxHPVzUj3gI5BwA6 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-bxHPVzUj3gI5BwA6 .sequenceNumber{fill:white;}#mermaid-svg-bxHPVzUj3gI5BwA6 #sequencenumber{fill:#333;}#mermaid-svg-bxHPVzUj3gI5BwA6 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-bxHPVzUj3gI5BwA6 .messageText{fill:#333;stroke:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bxHPVzUj3gI5BwA6 .labelText,#mermaid-svg-bxHPVzUj3gI5BwA6 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .loopText,#mermaid-svg-bxHPVzUj3gI5BwA6 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-bxHPVzUj3gI5BwA6 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-bxHPVzUj3gI5BwA6 .noteText,#mermaid-svg-bxHPVzUj3gI5BwA6 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-bxHPVzUj3gI5BwA6 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bxHPVzUj3gI5BwA6 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bxHPVzUj3gI5BwA6 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bxHPVzUj3gI5BwA6 .actorPopupMenu{position:absolute;}#mermaid-svg-bxHPVzUj3gI5BwA6 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-bxHPVzUj3gI5BwA6 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bxHPVzUj3gI5BwA6 .actor-man circle,#mermaid-svg-bxHPVzUj3gI5BwA6 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-bxHPVzUj3gI5BwA6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} socket() bind() listen() 三次握手完成 连接建立 四次挥手完成 连接关闭 SYN(同步请求) SYN-ACK(同步确认) ACK(确认) accept() 返回新套接字 发送数据 发送数据 FIN(结束请求) ACK(确认) FIN(结束请求) ACK(确认)
4.3 操作系统如何将数据交给正确的进程
当网卡接收到数据包时,操作系统需要完成以下步骤将数据交付给正确的进程:
第一步:网卡接收数据
网卡检测到物理信号,将电信号转换为数字数据,存储在网卡自身的缓冲区中。然后,网卡通过DMA(直接内存访问)将数据复制到内核预先分配的内存区域,并向CPU发送中断信号。
第二步:中断处理
CPU响应网卡中断,执行网卡驱动程序的中断处理函数。中断处理函数完成必要的硬件操作后,将数据包交给内核网络子系统处理,通常是将数据包放入一个队列中,触发软中断进行后续处理。
第三步:协议栈处理
软中断处理程序从队列中取出数据包,逐层进行协议处理:
数据链路层:解析以太网帧头,检查目的MAC地址,提取类型字段。
网络层:解析IP头部,检查目的IP地址,进行路由判断,提取协议类型(TCP/UDP/ICMP 等)。
传输层:解析TCP/UDP头部,提取源端口号和目的端口号。
第四步:套接字匹配
内核根据提取到的四元组信息(源 IP、源端口、目的 IP、目的端口),在套接字哈希表中查找匹配的套接字。如果找到匹配的套接字,就将数据包放入该套接字的接收缓冲区中。
第五步:唤醒进程
如果对应的应用进程正在等待数据(如阻塞在recv()调用上),内核会唤醒该进程,使其从系统调用返回,读取接收缓冲区中的数据。如果进程没有等待,数据就暂存在缓冲区中,等待进程下次读取。
#mermaid-svg-ZYdbjk4dsANsVdZH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZYdbjk4dsANsVdZH .error-icon{fill:#552222;}#mermaid-svg-ZYdbjk4dsANsVdZH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZYdbjk4dsANsVdZH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZYdbjk4dsANsVdZH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZYdbjk4dsANsVdZH .marker.cross{stroke:#333333;}#mermaid-svg-ZYdbjk4dsANsVdZH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZYdbjk4dsANsVdZH p{margin:0;}#mermaid-svg-ZYdbjk4dsANsVdZH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH .cluster-label text{fill:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH .cluster-label span{color:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH .cluster-label span p{background-color:transparent;}#mermaid-svg-ZYdbjk4dsANsVdZH .label text,#mermaid-svg-ZYdbjk4dsANsVdZH span{fill:#333;color:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH .node rect,#mermaid-svg-ZYdbjk4dsANsVdZH .node circle,#mermaid-svg-ZYdbjk4dsANsVdZH .node ellipse,#mermaid-svg-ZYdbjk4dsANsVdZH .node polygon,#mermaid-svg-ZYdbjk4dsANsVdZH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZYdbjk4dsANsVdZH .rough-node .label text,#mermaid-svg-ZYdbjk4dsANsVdZH .node .label text,#mermaid-svg-ZYdbjk4dsANsVdZH .image-shape .label,#mermaid-svg-ZYdbjk4dsANsVdZH .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZYdbjk4dsANsVdZH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZYdbjk4dsANsVdZH .rough-node .label,#mermaid-svg-ZYdbjk4dsANsVdZH .node .label,#mermaid-svg-ZYdbjk4dsANsVdZH .image-shape .label,#mermaid-svg-ZYdbjk4dsANsVdZH .icon-shape .label{text-align:center;}#mermaid-svg-ZYdbjk4dsANsVdZH .node.clickable{cursor:pointer;}#mermaid-svg-ZYdbjk4dsANsVdZH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZYdbjk4dsANsVdZH .arrowheadPath{fill:#333333;}#mermaid-svg-ZYdbjk4dsANsVdZH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZYdbjk4dsANsVdZH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZYdbjk4dsANsVdZH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZYdbjk4dsANsVdZH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZYdbjk4dsANsVdZH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZYdbjk4dsANsVdZH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZYdbjk4dsANsVdZH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZYdbjk4dsANsVdZH .cluster text{fill:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH .cluster span{color:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZYdbjk4dsANsVdZH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZYdbjk4dsANsVdZH rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZYdbjk4dsANsVdZH .icon-shape,#mermaid-svg-ZYdbjk4dsANsVdZH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZYdbjk4dsANsVdZH .icon-shape p,#mermaid-svg-ZYdbjk4dsANsVdZH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZYdbjk4dsANsVdZH .icon-shape .label rect,#mermaid-svg-ZYdbjk4dsANsVdZH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZYdbjk4dsANsVdZH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZYdbjk4dsANsVdZH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZYdbjk4dsANsVdZH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 网卡接收数据
DMA复制到内核内存
触发硬件中断
中断处理程序
数据包入队列
软中断处理
解析以太网帧
解析IP数据包
解析TCP/UDP段
提取四元组
查找套接字哈希表
匹配套接字
数据存入接收缓冲区
唤醒等待进程
进程读取数据
五、协议的本质:结构体
5.1 协议即约定
从编程的角度看,网络协议的本质就是结构体(struct)。每一层协议的头部都可以看作是一个C语言结构体,其中定义了该层协议所需的各种字段。从编程的角度看,网络协议的本质就是结构体(struct)。每一层协议的头部都可以看作是一个C语言结构体,其中定义了该层协议所需的各种字段。
例如,以太网帧头可以定义为:例如,以太网帧头可以定义为:
c
struct eth_header {
unsigned char dst_mac[6]; // 目的MAC地址
unsigned char src_mac[6]; // 源MAC地址
unsigned short type; // 上层协议类型
};
IP 头部可以定义为:IP 头部可以定义为:
c
struct ip_header {
unsigned char version_ihl; // 版本和头部长度
unsigned char tos; // 服务类型
unsigned short total_len; // 总长度
unsigned short id; // 标识
unsigned short flags_offset; // 标志和片偏移
unsigned char ttl; // 生存时间
unsigned char protocol; // 上层协议
unsigned short checksum; // 头部校验和
unsigned int src_ip; // 源IP地址
unsigned int dst_ip; // 目的IP地址
};
TCP 头部可以定义为:TCP 头部可以定义为:
c
struct tcp_header {
unsigned short src_port; // 源端口号
unsigned short dst_port; // 目的端口号
unsigned int seq_num; // 序列号
unsigned int ack_num; // 确认号
unsigned char data_offset; // 数据偏移
unsigned char flags; // 标志位
unsigned short window; // 窗口大小
unsigned short checksum; // 校验和
unsigned short urgent_ptr; // 紧急指针
};
5.2 协议的可扩展性
协议的设计需要考虑可扩展性。以IP协议为例,IPv4 的 32 位地址空间已经逐渐耗尽,因此推出了 IPv6,将地址长度扩展到 128 位。这种扩展性是通过协议头部的版本字段来实现的------IPv4 数据包和 IPv6 数据包可以通过版本字段(IPv4 为 4,IPv6 为 6)来区分。
同样,TCP 协议也通过选项字段支持各种扩展功能,如窗口扩大因子、时间戳、选择性确认(SACK)等,这些都是在不改变基本头部格式的情况下实现的。
六、理解IP 地址和目的 IP 地址
6.1 源IP与目的IP
在网络通信中,IP地址分为源IP地址和目的IP地址:在网络通信中,IP地址分为源IP地址和目的IP地址:
源IP地址:标识数据包的发送方。在TCP/IP 协议栈中,源IP地址通常由操作系统自动填写,取自发送网络接口的IP地址。但在某些场景下(如NAT、代理、负载均衡),源IP地址可能会被修改。源IP地址:标识数据包的发送方。在TCP/IP 协议栈中,源IP地址通常由操作系统自动填写,取自发送网络接口的IP地址。但在某些场景下(如NAT、代理、负载均衡),源IP地址可能会被修改。
目的IP地址:标识数据包的接收方。应用程序在建立连接时指定目的IP地址,操作系统根据目的IP地址进行路由选择,决定数据包的发送路径。目的IP地址:标识数据包的接收方。应用程序在建立连接时指定目的IP地址,操作系统根据目的IP地址进行路由选择,决定数据包的发送路径。
6.2 路由决策
当主机发送数据包时,操作系统需要进行路由决策:
检查目的IP地址是否与本机在同一子网。如果是,直接使用ARP 协议获取目的主机的MAC 地址,进行局域网内直接通信。
如果目的IP地址不在同一子网,则将数据包发送给默认网关(路由器)。路由器根据目的IP地址查询路由表,决定下一跳。
数据包经过多个路由器的转发,最终到达目的网络,再由目的网络内的路由器或交换机将数据包交付给目的主机。
#mermaid-svg-eLT45KRXzwCSY4yP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eLT45KRXzwCSY4yP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eLT45KRXzwCSY4yP .error-icon{fill:#552222;}#mermaid-svg-eLT45KRXzwCSY4yP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eLT45KRXzwCSY4yP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eLT45KRXzwCSY4yP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eLT45KRXzwCSY4yP .marker.cross{stroke:#333333;}#mermaid-svg-eLT45KRXzwCSY4yP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eLT45KRXzwCSY4yP p{margin:0;}#mermaid-svg-eLT45KRXzwCSY4yP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eLT45KRXzwCSY4yP .cluster-label text{fill:#333;}#mermaid-svg-eLT45KRXzwCSY4yP .cluster-label span{color:#333;}#mermaid-svg-eLT45KRXzwCSY4yP .cluster-label span p{background-color:transparent;}#mermaid-svg-eLT45KRXzwCSY4yP .label text,#mermaid-svg-eLT45KRXzwCSY4yP span{fill:#333;color:#333;}#mermaid-svg-eLT45KRXzwCSY4yP .node rect,#mermaid-svg-eLT45KRXzwCSY4yP .node circle,#mermaid-svg-eLT45KRXzwCSY4yP .node ellipse,#mermaid-svg-eLT45KRXzwCSY4yP .node polygon,#mermaid-svg-eLT45KRXzwCSY4yP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eLT45KRXzwCSY4yP .rough-node .label text,#mermaid-svg-eLT45KRXzwCSY4yP .node .label text,#mermaid-svg-eLT45KRXzwCSY4yP .image-shape .label,#mermaid-svg-eLT45KRXzwCSY4yP .icon-shape .label{text-anchor:middle;}#mermaid-svg-eLT45KRXzwCSY4yP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eLT45KRXzwCSY4yP .rough-node .label,#mermaid-svg-eLT45KRXzwCSY4yP .node .label,#mermaid-svg-eLT45KRXzwCSY4yP .image-shape .label,#mermaid-svg-eLT45KRXzwCSY4yP .icon-shape .label{text-align:center;}#mermaid-svg-eLT45KRXzwCSY4yP .node.clickable{cursor:pointer;}#mermaid-svg-eLT45KRXzwCSY4yP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eLT45KRXzwCSY4yP .arrowheadPath{fill:#333333;}#mermaid-svg-eLT45KRXzwCSY4yP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eLT45KRXzwCSY4yP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eLT45KRXzwCSY4yP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eLT45KRXzwCSY4yP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eLT45KRXzwCSY4yP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eLT45KRXzwCSY4yP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eLT45KRXzwCSY4yP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eLT45KRXzwCSY4yP .cluster text{fill:#333;}#mermaid-svg-eLT45KRXzwCSY4yP .cluster span{color:#333;}#mermaid-svg-eLT45KRXzwCSY4yP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eLT45KRXzwCSY4yP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eLT45KRXzwCSY4yP rect.text{fill:none;stroke-width:0;}#mermaid-svg-eLT45KRXzwCSY4yP .icon-shape,#mermaid-svg-eLT45KRXzwCSY4yP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eLT45KRXzwCSY4yP .icon-shape p,#mermaid-svg-eLT45KRXzwCSY4yP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eLT45KRXzwCSY4yP .icon-shape .label rect,#mermaid-svg-eLT45KRXzwCSY4yP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eLT45KRXzwCSY4yP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eLT45KRXzwCSY4yP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eLT45KRXzwCSY4yP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
否
是
发送数据包
目的IP在同一子网?
ARP获取目的MAC
直接发送
发送给默认网关
路由器查询路由表
到达目的网络?
转发到下一跳路由器
交付给目的主机
6.3 NAT 与端口映射
在 IPv4 地址短缺的情况下,NAT(网络地址转换) 技术被广泛使用。NAT 允许多台内网主机共享一个公网 IP 地址访问互联网。
NAT 设备(通常是路由器) 维护一张 NAT 转换表,,记录内网 IP 和端口与外网 IP 和端口的映射关系。当内网主机发送数据包时,NAT 设备将源 IP 地址替换为公网 IP 地址,并分配一个临时的源端口号;当收到回复数据包时,NAT 设备根据目的端口号查询 NAT 表,将数据包转发给对应的内网主机。
#mermaid-svg-Fni6gfvZkjyUnQ36{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Fni6gfvZkjyUnQ36 .error-icon{fill:#552222;}#mermaid-svg-Fni6gfvZkjyUnQ36 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Fni6gfvZkjyUnQ36 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .marker.cross{stroke:#333333;}#mermaid-svg-Fni6gfvZkjyUnQ36 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Fni6gfvZkjyUnQ36 p{margin:0;}#mermaid-svg-Fni6gfvZkjyUnQ36 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .cluster-label text{fill:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .cluster-label span{color:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .cluster-label span p{background-color:transparent;}#mermaid-svg-Fni6gfvZkjyUnQ36 .label text,#mermaid-svg-Fni6gfvZkjyUnQ36 span{fill:#333;color:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .node rect,#mermaid-svg-Fni6gfvZkjyUnQ36 .node circle,#mermaid-svg-Fni6gfvZkjyUnQ36 .node ellipse,#mermaid-svg-Fni6gfvZkjyUnQ36 .node polygon,#mermaid-svg-Fni6gfvZkjyUnQ36 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .rough-node .label text,#mermaid-svg-Fni6gfvZkjyUnQ36 .node .label text,#mermaid-svg-Fni6gfvZkjyUnQ36 .image-shape .label,#mermaid-svg-Fni6gfvZkjyUnQ36 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Fni6gfvZkjyUnQ36 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .rough-node .label,#mermaid-svg-Fni6gfvZkjyUnQ36 .node .label,#mermaid-svg-Fni6gfvZkjyUnQ36 .image-shape .label,#mermaid-svg-Fni6gfvZkjyUnQ36 .icon-shape .label{text-align:center;}#mermaid-svg-Fni6gfvZkjyUnQ36 .node.clickable{cursor:pointer;}#mermaid-svg-Fni6gfvZkjyUnQ36 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .arrowheadPath{fill:#333333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Fni6gfvZkjyUnQ36 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Fni6gfvZkjyUnQ36 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Fni6gfvZkjyUnQ36 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Fni6gfvZkjyUnQ36 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .cluster text{fill:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 .cluster span{color:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Fni6gfvZkjyUnQ36 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Fni6gfvZkjyUnQ36 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Fni6gfvZkjyUnQ36 .icon-shape,#mermaid-svg-Fni6gfvZkjyUnQ36 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Fni6gfvZkjyUnQ36 .icon-shape p,#mermaid-svg-Fni6gfvZkjyUnQ36 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Fni6gfvZkjyUnQ36 .icon-shape .label rect,#mermaid-svg-Fni6gfvZkjyUnQ36 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Fni6gfvZkjyUnQ36 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Fni6gfvZkjyUnQ36 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Fni6gfvZkjyUnQ36 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 互联网
内网
源:192.168.1.10:8888
源:203.0.113.1:50001
目的:203.0.113.1:50001
目的:192.168.1.10:8888
源:192.168.1.20:9999
源:203.0.113.1:50002
目的:203.0.113.1:50002
目的:192.168.1.20:9999
主机A
192.168.1.10:8888
主机B
192.168.1.20:9999
NAT路由器
公网IP: 203.0.113.1
服务器
198.51.100.1:80
七、进程间通信与网络通信的统一
7.1 本地进程间通信
在同一台主机上,进程间通信(IPC)有多种方式:管道(Pipe)、消息队列(Message Queue)、共享内存(Shared Memory)、信号量(Semaphore)等。这些机制都属于 System V IPC 或 POSIX IPC 标准。
7.2 网络通信的本质也是进程间通信
网络通信的本质,实际上是跨主机的进程间通信。网络通信的本质,实际上是跨主机的进程间通信。无论是本地通信还是网络通信,最终都是将数据从一个进程传递到另一个进程。区别在于:
本地通信:数据在同一台主机的内存中传递,不需要经过网络协议栈。本地通信:数据在同一台主机的内存中传递,不需要经过网络协议栈。
网络通信:数据需要经过网络协议栈的封装,通过物理介质传输到另一台主机,再经过协议栈解封装,最终交付给目标进程。网络通信:数据需要经过网络协议栈的封装,通过物理介质传输到另一台主机,再经过协议栈解封装,最终交付给目标进程。
Socket 接口的设计巧妙地统一了这两种通信方式。在 Linux 系统中,本地通信可以使用 Unix 域套接字(Unix Domain Socket),它使用文件系统路径作为地址,数据在内核中直接传递,效率高于网络套接字。而网络套接字则使用 IP 地址和端口号作为地址,数据通过网络传输。
#mermaid-svg-KW4B2xthyK4BHtCz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KW4B2xthyK4BHtCz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KW4B2xthyK4BHtCz .error-icon{fill:#552222;}#mermaid-svg-KW4B2xthyK4BHtCz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KW4B2xthyK4BHtCz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KW4B2xthyK4BHtCz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KW4B2xthyK4BHtCz .marker.cross{stroke:#333333;}#mermaid-svg-KW4B2xthyK4BHtCz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KW4B2xthyK4BHtCz p{margin:0;}#mermaid-svg-KW4B2xthyK4BHtCz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KW4B2xthyK4BHtCz .cluster-label text{fill:#333;}#mermaid-svg-KW4B2xthyK4BHtCz .cluster-label span{color:#333;}#mermaid-svg-KW4B2xthyK4BHtCz .cluster-label span p{background-color:transparent;}#mermaid-svg-KW4B2xthyK4BHtCz .label text,#mermaid-svg-KW4B2xthyK4BHtCz span{fill:#333;color:#333;}#mermaid-svg-KW4B2xthyK4BHtCz .node rect,#mermaid-svg-KW4B2xthyK4BHtCz .node circle,#mermaid-svg-KW4B2xthyK4BHtCz .node ellipse,#mermaid-svg-KW4B2xthyK4BHtCz .node polygon,#mermaid-svg-KW4B2xthyK4BHtCz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KW4B2xthyK4BHtCz .rough-node .label text,#mermaid-svg-KW4B2xthyK4BHtCz .node .label text,#mermaid-svg-KW4B2xthyK4BHtCz .image-shape .label,#mermaid-svg-KW4B2xthyK4BHtCz .icon-shape .label{text-anchor:middle;}#mermaid-svg-KW4B2xthyK4BHtCz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KW4B2xthyK4BHtCz .rough-node .label,#mermaid-svg-KW4B2xthyK4BHtCz .node .label,#mermaid-svg-KW4B2xthyK4BHtCz .image-shape .label,#mermaid-svg-KW4B2xthyK4BHtCz .icon-shape .label{text-align:center;}#mermaid-svg-KW4B2xthyK4BHtCz .node.clickable{cursor:pointer;}#mermaid-svg-KW4B2xthyK4BHtCz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KW4B2xthyK4BHtCz .arrowheadPath{fill:#333333;}#mermaid-svg-KW4B2xthyK4BHtCz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KW4B2xthyK4BHtCz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KW4B2xthyK4BHtCz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KW4B2xthyK4BHtCz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KW4B2xthyK4BHtCz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KW4B2xthyK4BHtCz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KW4B2xthyK4BHtCz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KW4B2xthyK4BHtCz .cluster text{fill:#333;}#mermaid-svg-KW4B2xthyK4BHtCz .cluster span{color:#333;}#mermaid-svg-KW4B2xthyK4BHtCz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KW4B2xthyK4BHtCz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KW4B2xthyK4BHtCz rect.text{fill:none;stroke-width:0;}#mermaid-svg-KW4B2xthyK4BHtCz .icon-shape,#mermaid-svg-KW4B2xthyK4BHtCz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KW4B2xthyK4BHtCz .icon-shape p,#mermaid-svg-KW4B2xthyK4BHtCz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KW4B2xthyK4BHtCz .icon-shape .label rect,#mermaid-svg-KW4B2xthyK4BHtCz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KW4B2xthyK4BHtCz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KW4B2xthyK4BHtCz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KW4B2xthyK4BHtCz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不同主机
网络套接字
TCP/IP
进程A
主机1
进程B
主机2
同一主机
Unix域套接字
进程A
进程B
7.3 为什么需要端口号而不是PID
一个常见的问题是:操作系统已经有进程 ID(PID)来标识进程了,为什么网络通信还需要引入端口号?
原因在于:
PID 是操作系统内部概念:PID 是操作系统分配给进程的本地标识,不同主机上的 PID 可能重复,无法在全球范围内唯一标识一个网络进程。
网络通信需要稳定的标识:进程的 PID 可能在进程重启后改变,但网络服务通常需要绑定到固定的端口号,以便客户端能够持续访问。
一个进程可以提供多个服务:一个进程可能同时提供多种网络服务(如同时监听 HTTP 和 HTTPS),使用不同的端口号可以区分这些服务。
端口号的层次更高:PID 是操作系统调度管理的概念,而端口号是网络通信的概念。将两者解耦,使得网络通信不依赖于特定的操作系统实现。
八、总结与展望
本文从网络协议的本质出发,系统梳理了网络通信的核心概念和机制:
协议的分层设计解决了网络通信的复杂性问题,每一层专注于特定的职责,通过定义良好的接口协同工作。
IP 地址和端口号共同构成了网络通信的寻址体系,IP 地址标识主机,端口号标识主机上的进程,四元组唯一标识一个通信连接。
Socket 编程接口为应用程序提供了简洁的网络通信能力,封装了底层协议的复杂性。
操作系统内核通过中断处理、协议栈解析、套接字匹配等机制,确保数据能够准确、高效地交付给目标进程。
协议的本质是结构体,这一认识有助于我们从编程的角度理解网络协议的设计和实现。
随着技术的发展,网络通信也在不断演进。IPv6 正在逐步替代 IPv4,提供更大的地址空间和更好的安全性;QUIC 协议基于 UDP 实现了类似 TCP 的可靠性,同时降低了连接建立延迟;HTTP/3 基于 QUIC,进一步提升了Web性能。但无论技术如何发展,本文所阐述的基本原理------分层设计、寻址机制、封装解封装、进程间通信------始终是理解网络通信的基石。