
💡Yupureki:个人主页
✨个人专栏:《C++》 《算法》《Linux系统编程》《高并发内存池》《MySQL数据库》
🌸Yupureki🌸的简介:

目录
[1. 初始协议](#1. 初始协议)
[1.1 什么是协议](#1.1 什么是协议)
[1.2 OSI七层模型](#1.2 OSI七层模型)
[1.3 TCP/IP模型](#1.3 TCP/IP模型)
[2. 网络传输基本流程](#2. 网络传输基本流程)
[2.1 MAC地址](#2.1 MAC地址)
[2.2 局域网通信原理](#2.2 局域网通信原理)
[2.3 数据报头](#2.3 数据报头)
[3. Socket编程预备](#3. Socket编程预备)
[3.1 网络中的地址](#3.1 网络中的地址)
[3.2 端口号](#3.2 端口号)
[3.2.1 什么是端口号](#3.2.1 什么是端口号)
[3.2.2 一些知名的默认端口号](#3.2.2 一些知名的默认端口号)
[3.2.3 源端口 vs 目标端口](#3.2.3 源端口 vs 目标端口)
[3.3 理解socket](#3.3 理解socket)
[3.4 传输层协议的典型代表](#3.4 传输层协议的典型代表)
[3.4.1 UDP协议](#3.4.1 UDP协议)
[3.4.2 TCP协议](#3.4.2 TCP协议)
[3.5 网络字节序](#3.5 网络字节序)
1. 初始协议
1.1 什么是协议
简单来说,网络协议 就是计算机网络中设备之间通信所共同遵守的规则、标准或约定。
就像两个人交谈需要共同的语言(比如中文或英语)一样,计算机、手机、服务器等网络设备在传输数据时,也必须遵循一套统一的协议,才能正确地发送、接收和理解信息。
核心要素
一个网络协议通常定义了三个关键方面:
-
语法:规定数据的格式、结构和编码方式。比如,数据包的开头应该是源地址,接着是目的地址,然后是数据内容等。
-
语义:规定每一部分数据的具体含义和解释方式,以及需要做出什么响应。比如,一个请求报文是要求"获取一个文件",还是"提交一个表单"。
-
时序:规定事件发生的顺序和速度控制。比如,客户端必须先发送请求,服务器才能回应;如果网络拥堵,发送方应该如何降低速度。
一个生活中的比喻
想象一下打电话的过程:
-
语法:你说话要用对方能听懂的语言(比如普通话),句子要有主谓宾的结构。
-
语义:"你好"表示问候和开始对话,"再见"表示要结束通话。听到"请稍等"就知道对方要让你等待。
-
时序:必须先拨号、接通、互相问好,然后才能谈论正事,最后告别挂断。你不能在拨号音还没结束时就开始说事情。
网络协议就是设备间进行这种"通话"所必须遵守的完整规则。
1.2 OSI七层模型
OSI(开放系统互连,Open Systems Interconnection)模型 是由国际标准化组织(ISO)在 1984 年提出的概念模型,旨在将复杂的网络通信过程分解为 7 个清晰的层次。每一层都承担特定的功能,并为上一层提供服务,同时使用下一层的服务。
核心思想 :对等通信 ------ 发送方的第 N 层与接收方的第 N 层逻辑上直接"对话",实际数据通过下层逐层传递。

它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整
通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯;
但是,它既复杂又不实用;所以我们按照TCP/IP四层模型来讲解。
1.3 TCP/IP模型
TCP/IP模型将网络通信划分为四个逻辑层次 ,每一层负责不同的任务,并且只与上下层交互。这个分层的设计,就像公司里的不同部门各司其职,好处是:如果某一层技术升级了(比如网线从铜线变光纤),其他层(比如你用的微信或浏览器)完全不需要改动。
| 层级 | 名称 | 核心职责 | 核心协议/技术 | 类比(寄快递) |
|---|---|---|---|---|
| 4 | 应用层 | 为用户提供网络服务 | HTTP, HTTPS, FTP, SMTP, DNS | 包裹里的货物(具体是什么东西) |
| 3 | 传输层 | 建立端到端的连接,保证可靠或高效传输 | TCP, UDP | 快递公司的服务类型(普通快递或加急件) |
| 2 | 网络层 | 寻址和路由,决定数据从哪条路到达目的地 | IP (IPv4/IPv6), ICMP, ARP | 快递上的地址标签(收件人地址) |
| 1 | 网络接口层 | 在物理网络上传输原始比特流 | 以太网, Wi-Fi, 光纤, 网卡驱动 | 运送包裹的交通工具和道路(货车、飞机、公路) |

2. 网络传输基本流程
2.1 MAC地址
互联网中的机器千千万万,我如何找到目标主机?通过唯一标识->MAC地址
MAC地址 (Media Access Control Address),直译为媒体访问控制地址 ,通俗理解就是网络设备的"物理身份证" 或**"硬件地址"**。
它是一个用来在网络中唯一标识一个网络接口控制器(比如你电脑的网卡、手机的无线网卡)的号码。就像每栋房子都有一个唯一且固定的门牌号,每个能联网的设备,其网络接口都有一个全世界独一无二的MAC地址。
它的长度为48比特位 ,即6个字节,一般用16进制数字加上冒号的形式来表示(例如:08:00:27:03:fb:19)
在网卡出厂时就确定了,不能修改.mac地址通常是唯一的(虚拟机中的mac地址不是真实的mac地
址,可能会冲突;也有些网卡支持用户配置mac地址).
2.2 局域网通信原理
一个简单局域网包含:
-
若干终端设备:电脑、手机、打印机等(每个设备有唯一的 MAC 地址)
-
网络交换设备 :最常用的是交换机(Switch)(现在基本不用集线器)
-
传输介质:网线或 Wi-Fi
注意:家用无线路由器 = 交换机 + 路由器 + AP 的集合体,但其"LAN口"部分本质上是一个交换机。

局域网中,任何时刻,只允许一台机器 向网络中发送数据。如果有多台同时发送,会发生数据干扰,我们称之为数据碰撞
如同上课时只允许老师一个人讲话,如果下面的学生也在讲,就会干扰上课效率。同时,当老师向某个学生提问时,点到这个学生的名字时,是只有这一个学生听见了还是全班都听见了?肯定是全班学生都听见了,但由于不是点的自己的名字,因此不会做处理
因此局域网通信的过程中,主机对收到的报文确认是否是发给自己 的,是通过目标mac地址判定
2.3 数据报头
在互联网中传输数据,可不能胡乱的传。就如同寄快递,可不是寄快递本身就够了,我们需要知道快递的信息,如送货人信息,收货人信息等
数据报头(Header) 就像是寄快递时贴在包裹上的快递单。
这张"快递单"上写明了:谁发的(源地址)、发给谁(目的地址)、用什么方式寄的(协议类型)、包裹的序号(用于重组)以及怎么检查包裹有没有破损(校验和)。而包裹里的实际物品,就是数据(Data/Payload)。
在 TCP/IP四层模型 中,数据每往下发一层,就会被贴上一层新的"快递单"(封装),这个过程就叫封装。到达对方后,再一层层地把"快递单"撕掉(解封装)。
TCP/IP 四层模型与报头
再次明确这四层(从用户数据到物理传输):
-
应用层:数据产生的地方(如HTTP请求、邮件)。
-
传输层:负责"端到端"连接,管理数据分段和可靠性(TCP/UDP)。
-
网络层:负责"路由寻址",把数据包从一台机器送到另一台机器(IP)。
-
网络接口层:负责"相邻节点传输",通过MAC地址在同一个局域网内传输。
数据报头详解(以发送"Hello"为例)
假设你要在浏览器里访问一个网站,发送一个"Hello"。
-
数据 :
"Hello"(应用层协议如HTTP会加自己的头,比如GET /index.html,但为了简化,我们就把"Hello"当作这层出来的数据)。 -
传输层:添加 TCP/UDP 报头: 系统会把数据
"Hello"切分成适合传输的大小,然后加上一个传输层报头。 -
网络层:添加 IP 报: 计算机把上一步的
TCP段整个当作数据,然后加上一个IP报头。 -
网络接口层:添加 以太网 报头: 计算机把上一步的
IP数据报整体当作数据,然后加上以太网报头。
当对方收到数据后,又会以反方向解包
总结:
-
发 :应用数据 → +TCP头 → +IP头 → +以太网头 → 比特流。
-
收 :比特流 → -以太网头 → -IP头 → -TCP头 → 应用数据。
3. Socket编程预备
3.1 网络中的地址
IP地址 是网络中标识设备的唯一地址
MAC地址 也是标识设备的唯一地址,和IP地址不是冲突了吗?
我们可以用一个生活化的类比来理解:
MAC地址 :是你与生俱来的身份证号(唯一、永久、不可更改)。
IP地址 :是你当前的居住地址(可变化、跟位置有关、用于收发快递)。
简单来说
MAC地址 :工作在数据链路层 (OSI模型的第2层)。负责在同一个局域网内部 (比如你的家庭Wi-Fi内)准确找到下一个要接收数据的设备。可以理解为**"同一街道内"的精准投递**。
IP地址 :工作在网络层 (OSI模型的第3层)。负责在不同网络之间 (比如从北京到纽约的互联网路径)规划数据传输的路由。可以理解为**"跨城市、跨国"的全局寻址**。
同时MAC地址永恒不变 ,设备出厂时就决定了。而IP地址经常变化,比如你切换wifi就变了
就像邮递员需要知道你的门牌号才能把信件送给你一样,网络中的信息(比如你看到的网页、发的微信消息)也需要通过IP地址,才能准确地从源头发送到你的电脑、手机或其他设备上。
两种主要的IP地址版本
目前最常用的是两种格式:IPv4 和 IPv6。
-
IPv4 :最常见的老格式,看起来像四组数字,用点隔开,例如
192.168.1.1。- 问题:总数只有约43亿个,而全球上网设备远超这个数,因此早已不够用。
-
IPv6 :为了解决IPv4地址枯竭问题而生的新格式,是一长串十六进制数,用冒号隔开,例如
2001:0db8:85a3:0000:0000:8a2e:0370:7334。- 优点:地址数量近乎无限,可以给地球上每一粒沙子都分配一个IP。
3.2 端口号
3.2.1 什么是端口号
在讲解端口号之前,我们需要明白一个观念:将数据传给主机不是目的,给人用才是最终目的
当数据传给主机时,怎么处理?让谁处理?日常生活中,我们很轻松地就启动了QQ,微信,数据传给了QQ和微信,经过了处理,让我们看到了聊天信息
因此,数据最终传给了主机中的某个进程,进程处理后再交给用户
那主机中的进程千千万万,我如何精准传给目标进程->标识主机中进程唯一性的数字,端口号
端口号是一个16位的整数 ,因此取值范围是 0 ~ 65535。这个范围被划分为三个部分:
分类 范围 说明 系统端口(Well-Known Ports) 0 ~ 1023 分配给系统级或常用网络服务。通常需要管理员权限才能使用。 注册端口(Registered Ports) 1024 ~ 49151 分配给用户进程或应用程序。许多常见软件(如数据库、游戏)会使用这些端口。 动态/私有端口(Dynamic/Private Ports) 49152 ~ 65535 临时分配给客户端程序。通常由操作系统自动分配,用于短暂通信。
因此我们以IP + Port 的形式,就能表示互联网上的唯一进程
3.2.2 一些知名的默认端口号
-
80:HTTP(普通网页访问)
-
443:HTTPS(加密网页访问)
-
21:FTP(文件传输协议)
-
22:SSH(安全外壳协议,用于远程登录)
-
25:SMTP(简单邮件传输协议,发邮件)
-
110:POP3(邮局协议,收邮件)
-
143:IMAP(更先进的邮件访问协议)
-
53:DNS(域名系统服务)
-
3306:MySQL数据库
-
5432:PostgreSQL数据库
-
6379:Redis数据库
-
27017:MongoDB数据库
-
8080:常用于HTTP代理或测试Web服务器(备用HTTP端口)
注意:这些只是"默认"约定。你完全可以配置Web服务器运行在8080或任意其它端口,只要客户端访问时指定该端口即可(例如
http://example.com:8080)。
3.2.3 源端口 vs 目标端口
在通信中,每个数据包都包含两个端口:
-
目标端口:接收方服务的端口(如访问百度时,目标端口是80或443)。
-
源端口:发送方临时随机生成的端口(通常大于1024,由操作系统分配)。
为什么需要源端口? 为了让接收方回复数据时,知道应该发回到你设备上的哪个"房间"。例如,你的浏览器可能使用 49152 作为源端口发起请求,百度服务器回复时,目标端口就是 49152,你的操作系统就知道这是属于那个浏览器标签页的数据。
3.3 理解socket
IP地址(定位设备)、端口号(定位设备上的具体服务),而 Socket 正是把这两个概念绑定在一起 ,形成一个网络通信的端点。
一句话理解 Socket
Socket = IP地址 + 端口号
它是操作系统提供给应用程序进行网络通信的编程接口 。你可以把 Socket 想象成一个电话插座------只要把电话线(网络连接)插进去,就能和另一端的人通话。
为什么要引入 Socket?
-
IP + 端口 只是逻辑上的定位,但应用程序如何实际发送和接收数据?需要一套函数(API)来创建连接、读写数据、关闭连接。
-
Socket 就是这样一套标准的网络编程接口。它封装了底层的TCP/UDP协议细节,让开发者可以像操作文件一样(打开->读写->关闭)进行网络通信。
3.4 传输层协议的典型代表
3.4.1 UDP协议
UDP(用户数据报协议)的设计目标是高效、快速,把可靠性保证交给上层的应用程序自己处理。
-
工作方式 :无连接。发送方不管对方是否在线、是否准备好,也不管网络状况如何,直接把数据包发出去,就像在邮局寄出一封明信片,不确认对方是否收到。
-
核心机制 :它几乎什么机制都没有。没有确认、没有重传、没有排序、没有流量和拥塞控制。UDP唯一做的事就是:给数据包加个端口号,然后扔到网络里。
-
优点与缺点:
-
优点 :速度快、开销小、延迟低。不需要握手、挥手、确认,代码简单,系统资源占用极少。
-
缺点 :不可靠 。数据可能丢失、重复、乱序,发送方完全不知道。应用程序收到什么就是什么,需要自己处理这些问题。
-
-
典型应用 :允许偶尔丢包 ,但对实时性要求很高的场景。
-
实时音视频通话 (VoIP, 视频会议):偶尔花屏或卡顿一下可以接受,但如果为了等丢失的包而延迟半秒,对话体验会非常差。
-
在线游戏:游戏里角色位置、动作的数据频繁更新。丢掉一两个最新的状态包没关系,但用TCP等待重传会导致明显的卡顿和延迟。
-
直播流媒体:直播偶尔出现马赛克或跳帧可以忍受,但持续的缓冲等待(TCP重传导致)会让人抓狂。
-
域名系统 (DNS):查询一个域名对应什么IP,就是一个简单的"问-答"。用一个UDP包来回一次就够了,效率最高。
-
3.4.2 TCP协议
TCP(传输控制协议)的设计目标是可靠、不丢数据,哪怕牺牲一些速度和效率。
-
工作方式:传输数据前,通信双方要先通过"三次握手"建立一个虚拟连接,就像打电话先拨号、等对方接通一样。传输结束后,还要通过"四次挥手"来断开连接。
-
核心机制:
-
确认与重传 :发送方发出数据后,必须等接收方确认收到了。如果长时间没收到确认,就认为数据丢了,会自动重发一次。
-
数据有序性 :每个数据包都有编号。即使数据乱序到达,TCP也会在接收端把它们重新排序,交给应用程序。
-
流量控制:发送方会根据接收方的处理能力动态调整发送速度,防止接收方来不及处理而被"压垮"。
-
拥塞控制:如果检测到网络中间有拥堵(比如很多包丢了),发送方会主动放慢速度,为其他连接让路。
-
-
优点与缺点:
-
优点 :可靠、有序、无差错。你发什么,对方就收到什么,顺序也完全一致。
-
缺点 :速度慢、效率低、占用系统资源多。因为要建立连接、确认、重传、排序,延迟较高。
-
-
典型应用 :任何数据绝对不能出错的场景。
-
网页浏览 (HTTP/HTTPS):网页代码或图片少一个字节都可能显示错误。
-
文件传输 (FTP):下载的文件损坏了就无法使用。
-
电子邮件 (SMTP/POP3):邮件内容不能有差错。
-
数据库连接:数据必须严格一致。
-
3.5 网络字节序
我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分,那么如何定义网络数据流的地址呢?
网络字节序(Network Byte Order)是 TCP/IP 协议中规定的一种标准字节序,统一使用大端序(Big-Endian) 。简单说:多字节数据的高位字节存储在内存的低地址处。
例如,十六进制数 0x12345678 在网络中传输时,顺序是:12 34 56 78(高位 12 最先发送)。
为什么需要它?
不同 CPU 的字节序不同:
-
大端序:网络字节序、PowerPC、68k、ARM(默认大端模式时)
-
小端序:x86、x86_64、ARM(通常作为小端模式运行)
如果不统一,双方直接交换内存数据,解析出来的值会完全错乱(比如 0x12345678 被小端机读成 0x78563412)。
因此所有多字节整数(uint16_t、uint32_t 等)在填充到发送缓冲区前,必须用转换函数转为网络字节序。
cpp
// 推荐使用标准函数
uint32_t htonl(uint32_t hostlong); // host to network long (32位)
uint16_t htons(uint16_t hostshort); // host to network short (16位)
uint32_t ntohl(uint32_t netlong); // network to host long
uint16_t ntohs(uint16_t netshort); // network to host short