网络通信与协议栈 -- OSI,TCP/IP模型,协议族,UDP编程
网络通信的核心是实现不同主机上进程间的数据交换,其技术体系围绕 “协议分层模型” 展开,向下依赖硬件介质传输电 / 光信号,向上支撑各类网络应用(如网页浏览、文件传输)。本文结合 OSI 理论框架与 TCP/IP 工业标准,从模型、协议、地址、配置、编程到架构,系统梳理网络通信核心知识。
一、网络通信的核心模型:OSI 与 TCP/IP 的对应与差异
网络通信需通过 “分层协作” 实现 —— 每层专注解决一类问题(如寻址、传输可靠性),并为上层提供标准化接口。OSI 七层模型是理论参考框架,TCP/IP 四层模型是实际工业标准,二者并非替代关系,而是 “理论指导实践” 的映射关系。
1. 分层模型对比(含功能、协议、设备)
OSI 七层模型(理论) | 核心功能拆解 | TCP/IP 四层模型(实用) | 对应功能整合(含 OSI 多层逻辑) | 关键协议 / 技术 | 典型硬件 / 载体 |
---|---|---|---|---|---|
应用层 | 为终端用户提供具体网络服务(如 “浏览网页”“发送邮件”),定义应用程序与网络的交互规则 | 应用层 | 整合 OSI 应用层 + 表示层 + 会话层功能,直接面向应用程序提供 API | HTTP/HTTPS、FTP、DNS、SMTP、DHCP | 浏览器、邮件客户端、FTP 工具 |
表示层 | 1. 数据格式转换(如 ASCII 与 UTF-8 编码转换);2. 数据压缩 / 解压(如 gzip);3. 加密 / 解密(如 SSL/TLS) | 应用层 | 功能隐含在应用层协议中,无需单独实现(例:HTTPS 通过 TLS 完成加密,HTTP 响应头通过Content-Encoding 指定压缩格式) | SSL/TLS、gzip、Base64 编码 | 操作系统协议栈、应用程序 |
会话层 | 1. 建立 / 终止进程间会话(如 WebSocket 连接握手);2. 会话管理(如 HTTP Keep-Alive 保持连接);3. 会话恢复(如断网后重连) | 应用层 | 功能通过应用协议或传输层机制实现(例:HTTP/1.1 的Connection: Keep-Alive ,TCP 的连接状态管理) | WebSocket、HTTP Keep-Alive、会话令牌(如 JWT) | 应用服务器、浏览器 |
传输层 | 1. 端到端(进程到进程)通信定位(通过端口号);2. 传输可靠性控制(重传、确认);3. 流量控制(避免接收方缓冲区溢出) | 传输层 | 与 OSI 传输层功能完全对齐,是 “进程通信可靠性” 的核心保障 | TCP、UDP、TCP 滑动窗口机制、UDP 校验和 | 主机操作系统(内核协议栈) |
网络层 | 1. 跨网络主机定位(通过 IP 地址);2. 路由选择(选择从源主机到目标主机的最优路径);3. 数据包分片 / 重组(解决 MTU 限制) | 网络层 | 与 OSI 网络层功能完全对齐,是 “跨网段通信” 的核心 | IP(IPv4/IPv6)、ICMP、IGMP、RIP/OSPF(路由协议) | 路由器、三层交换机 |
数据链路层 | 1. 物理相邻设备定位(通过 MAC 地址);2. 数据成帧(将 IP 数据包封装为 “帧”,添加帧头 / 帧尾);3. 差错控制(通过 CRC 校验丢弃错误帧);4. 介质访问控制(如以太网 CSMA/CD 避免冲突) | 接口层(链路层 + 物理层) | 整合 OSI 数据链路层 + 物理层功能,负责 “物理介质上的帧传输” | 以太网协议(Ethernet)、ARP、RARP、PPP(拨号协议) | 交换机、网卡、网桥 |
物理层 | 1. 定义物理介质特性(如双绞线线序、光纤波长);2. 信号转换(将 “帧” 的二进制数据转为电 / 光信号);3. 比特同步(确保发送方与接收方时钟一致) | 接口层(链路层 + 物理层) | 功能隐含在硬件设备中,无需软件配置(例:网卡将数字信号转为电信号,WiFi 将信号转为无线电波) | 双绞线(CAT5/CAT6)、光纤、WiFi(2.4GHz/5GHz)、以太网电信号标准(100Mbps/1Gbps) | 网卡、双绞线、光纤、无线路由器 |
2. 核心差异:OSI 与 TCP/IP 的本质区别
- 设计目标不同:OSI 追求 “通用性”(适配所有网络场景),TCP/IP 追求 “实用性”(解决互联网通信问题);
- 分层粒度不同:OSI 拆分更细(如将 “应用相关功能” 拆分为 3 层),TCP/IP 合并冗余层(将表示层、会话层融入应用层);
- 实现难度不同:OSI 理论复杂,未大规模落地;TCP/IP 简洁高效,成为全球互联网的标准。
二、TCP/IP 协议族:分层协议详解(从应用到接口)
TCP/IP 协议族是 “四层模型” 的具体实现,每层包含多个协议,协同完成数据传输。数据从应用层到接口层会逐层封装(添加头部信息),接收端则逐层解封装,最终还原原始数据。
1. 应用层协议:面向具体网络服务
应用层协议直接与应用程序交互,定义 “数据格式” 和 “交互流程”,解决 “用户需要什么服务” 的问题。
协议名称 | 核心功能 | 应用场景 | 关键细节 |
---|---|---|---|
HTTP(超文本传输协议) | 传输超文本数据(HTML、CSS、JS),是网页浏览的核心协议 | 浏览器访问网页、API 接口调用(如前后端交互) | - 基于 TCP,默认端口 80; - 无状态(每次请求独立,需 Cookie/Session 保持登录); - 版本:HTTP/1.1(支持 Keep-Alive)、HTTP/2(多路复用)、HTTP/3(基于 QUIC,UDP 协议) |
HTTPS(HTTP 安全版) | 在 HTTP 基础上添加 TLS 加密层,保障数据传输安全(防窃听、防篡改) | 支付、登录、敏感数据传输(如网银) | - 默认端口 443; - 需 SSL 证书验证服务器身份; - 加密流程:握手→密钥协商→数据加密传输 |
DNS(域名系统) | 将 “域名”(如www.baidu.com)解析为 “IP 地址”(如 180.101.49.12),解决 “记 IP 难” 问题 | 所有网络应用(需通过域名访问的场景) | - 基于 UDP(查询)和 TCP(zone 传输),默认端口 53; - 分层解析:根域名服务器→顶级域名服务器→权威域名服务器; - 缓存机制:本地 DNS 缓存(如路由器)、浏览器缓存 |
DHCP(动态主机配置协议) | 自动为局域网主机分配 IP 地址、子网掩码、网关、DNS,避免手动配置 | 家庭网、企业网(多主机场景) | - 基于 UDP,服务器端口 67,客户端端口 68; - 分配流程:发现(DHCP Discover)→提供(Offer)→请求(Request)→确认(ACK); - 租约期限:默认 24 小时,到期前需续租 |
FTP(文件传输协议) | 实现客户端与服务器间的文件上传(PUT)、下载(GET) | 网站运维(上传网页文件)、大文件传输 | - 基于 TCP,控制端口 21(传输指令),数据端口 20(传输文件); - 模式:主动模式(服务器主动连客户端)、被动模式(客户端主动连服务器); - 安全性低(明文传输账号密码),替代方案:SFTP(基于 SSH) |
TFTP(简单文件传输协议) | 轻量级文件传输协议,功能简化(无身份验证、仅支持文件传输) | 局域网设备配置(如路由器刷固件) | - 基于 UDP,默认端口 69; - 仅支持读(RRQ)、写(WRQ)操作; - 适合小文件(如配置文件),不适合大文件(无差错恢复优化) |
SMTP(简单邮件传输协议) | 负责 “发送邮件”(从发件人服务器到收件人服务器) | 邮件客户端(如 Outlook、网易邮箱) | - 基于 TCP,默认端口 25(非加密)、465(SSL 加密); - 需配合 POP3/IMAP 协议(接收邮件)使用; - 发送流程:连接→认证→发送邮件→断开 |
SNMP(简单网络管理协议) | 监控网络设备状态(如路由器流量、交换机端口状态),实现网络运维自动化 | 企业网运维(管理多设备) | - 基于 UDP,默认端口 161(代理)、162(陷阱); - 核心组件:管理站(监控端)、代理(被监控设备)、MIB(管理信息库,定义设备可监控的参数) |
2. 传输层协议:保障端到端(进程间)传输
传输层通过 “端口号” 定位主机上的进程,解决 “数据发给哪个应用” 的问题,核心协议为 TCP 和 UDP,二者按需选择使用。
协议名称 | 核心特性 | 工作机制 | 适用场景 | 头部大小 | 对比优势与劣势 |
---|---|---|---|---|---|
TCP(传输控制协议) | 面向连接、可靠传输、流量控制、拥塞控制 | 1. 连接建立:三次握手(SYN→SYN+ACK→ACK); 2. 可靠传输:确认(ACK)、重传(超时 / 快速重传)、排序(序号字段); 3. 流量控制:滑动窗口(根据接收方缓冲区调整发送速率); 4. 拥塞控制:慢启动、拥塞避免(避免网络拥堵); 5. 连接关闭:四次挥手(FIN→ACK→FIN→ACK) | 文件传输(FTP/SFTP)、网页(HTTP/HTTPS)、邮件(SMTP)等需 “数据不丢失” 的场景 | 20-60 字节 | 优势:数据可靠、无丢包乱序; 劣势:延迟高(握手 / 重传)、开销大(头部字段多) |
UDP(用户数据报协议) | 无连接、不可靠传输、低延迟、数据报边界 | 1. 无连接:直接发送数据,无需握手; 2. 不可靠:仅校验头部(校验和字段),出错则丢弃,不重传; 3. 数据报边界:发送 1 次对应接收 1 次,不合并 / 拆分数据; 4. 无流量 / 拥塞控制:按发送方速率传输 | 视频通话(如 Zoom)、游戏(如王者荣耀)、DNS 查询、实时监控等需 “低延迟” 的场景 | 8 字节 | 优势:延迟低、开销小、适合实时场景; 劣势:数据可能丢包 / 乱序,需应用层处理 |
3. 网络层协议:实现跨网络主机定位与路由
网络层通过 “IP 地址” 定位跨网段的主机,解决 “数据发给哪个主机” 的问题,同时通过路由协议选择最优传输路径。
协议名称 | 核心功能 | 关键细节 |
---|---|---|
IP(互联网协议) | 1. 定义 IP 地址格式(如 IPv4 的 32 位、IPv6 的 128 位); 2. 封装 IP 数据包(添加源 / 目标 IP); 3. 数据包分片 / 重组(当数据包超过 MTU 时,分片传输,接收端重组) | - IPv4:点分十进制(如 192.168.1.1),地址池即将耗尽; - IPv6:冒分十六进制(如 2001:0db8:85a3:0000:0000:8a2e:0370:7334),解决地址不足问题; - 无连接:仅负责转发,不保证送达(可靠性由 TCP 保障) |
ICMP(互联网控制消息协议) | 1. 网络诊断(如 ping 测试连通性); 2. 错误通知(如目标不可达、超时); 3. 路由控制(如重定向) | - 基于 IP 协议(封装在 IP 数据包中),无端口号; - ping 命令:发送 ICMP Echo Request,接收方回复 Echo Reply; - traceroute 命令:通过 ICMP 超时消息跟踪路由路径 |
IGMP(互联网组管理协议) | 管理主机与路由器间的 “组播” 关系(如主机加入 / 退出组播组) | - 组播地址:D 类 IP 地址(224.0.0.0~239.255.255.255); - 应用场景:视频会议(同一组播组内的主机接收相同视频流)、直播 |
路由协议(RIP/OSPF) | 路由器间交换路由信息,生成 “路由表”,选择从源到目标的最优路径 | - RIP(路由信息协议):基于 “跳数”(每经过一个路由器为 1 跳)选择路径,最大跳数 15(超过视为不可达),适合小型网络; - OSPF(开放式最短路径优先):基于 “链路成本”(如带宽、延迟)计算最短路径,适合大型网络(如企业网、互联网骨干网) |
4. 接口层协议:实现物理相邻设备通信
接口层负责 “物理介质上的帧传输”,通过 “MAC 地址” 定位同一网段的设备,解决 “数据发给哪个物理设备” 的问题。
协议名称 | 核心功能 | 关键细节 |
---|---|---|
以太网协议(Ethernet) | 1. 定义 “帧” 格式(添加源 / 目标 MAC 地址、帧校验位); 2. 介质访问控制(CSMA/CD:载波监听多路访问 / 冲突检测,避免同一网段设备同时发数据) | - MAC 地址:6 字节(如 00:1A:2B:3C:4D:5E),全球唯一(烧录在网卡中); - 帧结构:前导码(同步)+ 帧首定界符 + 目的 MAC + 源 MAC + 类型字段(如 0x0800 表示 IP 数据包) + 数据 + CRC 校验位; - 传输介质:双绞线(CAT5/CAT6)、光纤、同轴电缆 |
ARP(地址解析协议) | 将 “IP 地址” 转换为 “MAC 地址”(同一网段内通信需 MAC 地址) | - 工作流程:主机 A 要发数据给主机 B(同一网段)→ 广播 ARP 请求(“谁是 192.168.1.100?请回复 MAC”)→ 主机 B 回复 ARP 应答(“我是 192.168.1.100,MAC 是 00:1A:2B:3C:4D:5E”)→ 主机 A 缓存 ARP 表(IP→MAC 映射,默认缓存 10-20 分钟); - 跨网段场景:主机 A 发数据给跨网段主机 C→ ARP 请求网关 MAC→ 网关转发数据 |
RARP(反向地址解析协议) | 将 “MAC 地址” 转换为 “IP 地址”(适合无磁盘工作站,无法存储 IP 配置) | - 工作流程:无磁盘主机启动→ 广播 RARP 请求(“我的 MAC 是 00:1A:2B:3C:4D:5E,请分配 IP”)→ RARP 服务器回复 IP 地址; - 现在已被 DHCP 替代(DHCP 更灵活,可分配网关、DNS) |
PPP(点对点协议) | 实现 “点对点” 设备通信(如拨号上网:电脑通过 Modem 连运营商服务器) | - 无 MAC 地址(点对点无需广播); - 功能:链路建立、身份验证(PAP/CHAP)、数据压缩; - 早期 ADSL 拨号上网的核心协议,现在逐渐被光纤 PPPoE 替代 |
三、IP 地址:主机的 “网络身份证”(分类、特殊地址)
IP 地址是网络层用于定位主机的 “唯一标识”(IPv4 为 32 位二进制数,IPv6 为 128 位),分为 “网络号”(标识网段)和 “主机号”(标识网段内主机),通过子网掩码区分二者边界。
1. IPv4 地址分类
IPv4 地址采用 “点分十进制” 表示(如 192.168.1.1),根据 “前几位二进制数” 分为 A-E 五类,核心区别在于 “网络号 / 主机号位数” 和 “适用场景”。
地址类别 | 范围(点分十进制) | 网络号位数 | 主机号位数 | 默认子网掩码 | 适用场景 |
---|---|---|---|---|---|
A 类 | 1.0.0.0 ~ 126.255.255.255 | 8 | 24 | 255.0.0.0 | 超大规模网络(如早期互联网主干、大型跨国企业) |
B 类 | 128.0.0.0 ~ 191.255.255.255 | 16 | 16 | 255.255.0.0 | 中大规模网络(如中型企业、高校校园网) |
C 类 | 192.0.0.0 ~ 223.255.255.255 | 24 | 8 | 255.255.255.0 | 中小规模网络(如家庭网、办公室、小型门店) |
D 类 | 224.0.0.0 ~ 239.255.255.255 | 无(组播地址无网络号 / 主机号划分) | 无 | 无 | 组播通信(如视频会议、直播、IPTV) |
E 类 | 240.0.0.0 ~ 255.255.255.255 | 无 | 无 | 无 | 科研实验、未来扩展(未商用) |
2.特殊地址
-
127.0.0.1:本地回环地址
-
192.168.x.0:网络地址
-
192.168.x.1:通常为网关地址
-
192.168.x.255:广播地址
四、单机上网配置:从 “硬件” 到 “测试” 的全流程
单机(如 Linux 主机)要接入网络,需完成 “硬件准备→参数配置→连通性测试” 三步,核心是确保 “IP、网关、DNS” 三大参数正确。
1. 配置前提(硬件与软件)
- 硬件:有网络接口(如以太网网卡、无线网卡),插入网线(有线)或连接 WiFi(无线);
- 软件:操作系统支持 TCP/IP 协议栈(如 Linux、Windows、macOS 均默认支持)。
2. 关键配置参数(以 Linux 为例)
配置项 | 作用 | 配置文件 / 命令 | 示例配置 |
---|---|---|---|
IP 地址 | 标识本机在网段内的唯一身份 | 配置文件:/etc/network/interfaces (静态 IP)命令: dhclient (动态获取 IP) | 静态:address 192.168.1.100 |
子网掩码 | 区分 IP 地址中的 “网络号” 和 “主机号” | 同 IP 配置文件 | netmask 255.255.255.0 |
网关 | 本机跨网段通信的 “出口” | 命令:route add default gw 192.168.1.1 (临时生效) | gateway 192.168.1.1 |
DNS | 将域名(如www.baidu.com )解析为 IP 地址,实现 “域名访问” | 配置文件:/etc/resolv.conf | nameserver 8.8.8.8 (谷歌 DNS) |
3. 配置验证与网络诊断命令
命令 | 作用 | 示例输出说明 |
---|---|---|
ifconfig /ip addr | 查看网卡信息(IP、MAC、网卡状态) | eth0: inet 192.168.1.100/24 (正常) |
route -n /ip route | 查看路由表(确认网关是否生效) | default via 192.168.1.1 dev eth0 |
ping <IP/域名> | 测试与目标主机的连通性(基于 ICMP 协议) | 64 bytes from 202.108.22.5: icmp_seq=1 ttl=56 time=8.2ms (连通) |
nslookup <域名> | 测试 DNS 解析是否正常 | Name: www.baidu.com Address: 180.101.49.12 (解析成功) |
netstat -anp | 查看本机所有网络连接(含端口、进程 PID) | tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1234/nginx (80 端口被 nginx 占用) |
五、网络接口:进程与网络的 “桥梁”(Socket)
进程要通过网络通信,必须借助Socket(套接字) —— 它是操作系统提供的 “网络通信接口”,本质是一个 “文件描述符”(Linux 中 “一切皆文件”,网络通信即 “读写 Socket 文件”)。
1. Socket 的核心作用
- 封装底层协议:进程无需关注 TCP/UDP、IP、ARP 等底层细节,只需调用 Socket API(如
socket()
、bind()
、recvfrom()
); - 定位通信目标:通过 “IP + 端口号” 确定 “目标主机 + 目标进程”,即
(IP, Port)
二元组唯一标识一个网络进程。
2. 端口号:进程的 “网络门牌号”
- 范围:1~65535(16 位无符号整数);
- 分类:
- 知名端口(1~1023):系统 / 常用服务占用(如 HTTP 80、HTTPS 443、SSH 22、FTP 21);
- 动态端口(1024~65535):客户端进程临时使用(如浏览器访问网页时随机分配一个端口);
- 特性:TCP 和 UDP 端口独立(如 TCP 80 和 UDP 80 是两个不同端口,可同时被占用)。
六、网络字节序:大端
网络传输采用大端存储格式(高位字节在前),主机字节序,通常为小端模式(x86架构),需通过转换函数确保数据一致性:
数字转换函数(#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong); // 主机字节序 → 网络字节序(32位)
uint16_t htons(uint16_t hostshort); // 主机字节序 → 网络字节序(16位)
uint32_t ntohl(uint32_t netlong); // 网络字节序 → 主机字节序(32位)
uint16_t ntohs(uint16_t netshort); // 网络字节序 → 主机字节序(16位)
- 理想运行结果:
htonl(0x12345678)
返回0x78563412
(大端格式)
七、UDP 编程:无连接的 “数据报传输”
UDP 是传输层 “无连接、不可靠” 协议,适合对延迟敏感、可容忍少量丢包的场景(如视频通话、游戏、DNS 查询)。其编程模型分为服务端和客户端,流程简单且无连接建立过程。
1. UDP 的核心特性
- 无连接:通信前无需 “三次握手” 建立连接,直接发送数据;
- 不可靠:不保证数据送达(可能丢包)、不保证顺序(可能乱序)、不保证不重复(可能重传);
- 数据报边界:发送端每调用一次
sendto()
,接收端需调用一次recvfrom()
接收完整数据(如发送端发 2 次 100 字节,接收端不能一次收 200 字节); - 丢包原因:除了 “网络拥堵”,还可能是接收端
recvfrom()
调用不及时(缓冲区满)、发送速率超过接收速率(如服务器写硬盘慢于客户端发数据)。
2. UDP 通信框架
C/S模式通信流程:
3.UDP 编程流程(以 C 语言 Socket API 为例)
角色 | 核心步骤 | API 调用逻辑 |
---|---|---|
服务端 | 1. 创建 Socket → 2. 绑定 IP + 端口 → 3. 接收客户端数据 → 4. 发送响应数据 → 5. 关闭 Socket | 1. socket(AF_INET, SOCK_DGRAM, 0) (创建 UDP Socket)2. bind(sockfd, &addr, sizeof(addr)) (绑定端口)3. recvfrom(sockfd, buf, len, 0, &cli_addr, &cli_len) (阻塞接收)4. sendto(sockfd, buf, len, 0, &cli_addr, cli_len) (发送响应)5. close(sockfd) |
客户端 | 1. 创建 Socket → 2. 发送数据到服务端 → 3. 接收服务端响应 → 4. 关闭 Socket | 1. socket(AF_INET, SOCK_DGRAM, 0) (创建 UDP Socket,无需绑定端口,系统自动分配)2. sendto(sockfd, buf, len, 0, &serv_addr, sizeof(serv_addr)) (发送数据)3. recvfrom(sockfd, buf, len, 0, NULL, NULL) (接收响应)4. close(sockfd) |
关键函数说明
int socket(int domain, int type, int protocol);
- 功能:向内核申请创建基于内存的套接字描述符
- 参数:
domain
:地址族(PF_INET/AF_INET
用于互联网程序,PF_UNIX/AF_UNIX
用于单机程序)type
:套接字类型(SOCK_STREAM
=TCP流式套接字,SOCK_DGRAM
=UDP数据报套接字,SOCK_RAW
=原始套接字)protocol
:协议(0表示自动适配应用层协议)
- 返回值:成功返回套接字ID,失败返回-1
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
- 功能:
-
- 服务器端:将套接字与指定接口地址关联,用于接收数据
- 客户端:指定数据发送的源接口(通常可省略)
- 参数:
sockfd
:socket()返回的套接字IDmy_addr
:物理接口结构体指针(通用结构sockaddr
或专用结构sockaddr_in
)addrlen
:参数2的长度
- 返回值:成功返回0,失败返回-1
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
- 功能:UDP协议中向对方发送数据
- 参数:
sockfd
:本地套接字IDbuf
:发送数据缓冲区len
:数据长度flags
:发送方式(0=阻塞)dest_addr
:目标主机地址结构体(必选)addrlen
:目标地址长度
- 返回值:成功返回发送字节数,失败返回-1
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
- 功能:UDP协议中接收对方数据
- 参数:
sockfd
:本地套接字IDbuf
:接收数据缓冲区len
:缓冲区大小flags
:接收方式(0=阻塞)src_addr
:对方地址结构体(可选,NULL表示不关心)addrlen
:对方地址长度指针
- 返回值:成功返回接收字节数,失败返回-1
UDP 服务器代码示例
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>typedef struct sockaddr * (SA); // 定义sockaddr指针别名
int main(int argc, char **argv)
{// 创建UDP套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("socket"); // 打印错误信息return 1;}// 配置服务器地址结构struct sockaddr_in ser, cli;ser.sin_family = AF_INET; // IPv4协议族ser.sin_port = htons(50000); // 主机转网络字节序端口ser.sin_addr.s_addr = inet_addr("192.168.14.128"); // 设置IP地址// 绑定套接字到指定地址int ret = bind(sockfd, (SA) &ser, sizeof(ser));if (-1 == ret){perror("bind"); // 绑定失败处理return 1;}time_t tm;socklen_t len = sizeof(cli);while (1) // 持续服务循环{char buf[512] = {0}; // 接收缓冲区time(&tm); // 获取当前时间// 接收客户端数据(阻塞等待)recvfrom(sockfd, buf, sizeof(buf), 0, (SA)&cli, &len);// 附加时间戳到消息sprintf(buf, "%s %s", buf, ctime(&tm));// 将处理后的消息回传客户端sendto(sockfd, buf, strlen(buf), 0, (SA)&cli, len);}return 0; // 理想结果:持续运行并处理客户端请求
}
UDP 客户端代码示例
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>typedef struct sockaddr * (SA); // 定义sockaddr指针别名
int main(int argc, char **argv)
{// 创建UDP套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("socket"); // 错误处理return 1;}// 配置服务器地址结构struct sockaddr_in ser;ser.sin_family = AF_INET; // IPv4协议族ser.sin_port = htons(50000); // 主机转网络字节序端口ser.sin_addr.s_addr = inet_addr("192.168.14.128"); // 服务器IPint i = 10;while (i--) // 发送10次请求{char buf[512] = "hello,this udp test"; // 初始化消息// 发送数据到服务器sendto(sockfd, buf, strlen(buf), 0, (SA)&ser, sizeof(ser));bzero(buf, sizeof(buf)); // 清空缓冲区// 接收服务器响应(阻塞等待)recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);printf("from ser:%s\n", buf); // 打印服务器响应sleep(1); // 间隔1秒}close(sockfd); // 关闭套接字return 0; // 理想结果:输出10次类似 "from ser:hello,this udp test Wed Jun 12 10:30:45 2024"
}
八、网络通信模型:C/S、B/S 与 P2P
不同场景下,网络通信采用不同的 “角色分工模型”,核心区别在于 “资源存储位置” 和 “客户端形态”。
1. C/S 模型(客户端 / 服务器模型)
- 定义:由 “专用客户端” 和 “中心服务器” 组成,服务器提供资源 / 服务,客户端请求并处理资源;
- 核心特点:
- 客户端:专用(如 QQ、微信、游戏客户端),需安装,功能复杂(可本地处理大量数据);
- 协议:灵活(可自定义 TCP/UDP 协议,也可使用标准协议如 FTP);
- 资源:部分资源在客户端(如游戏客户端的本地地图、QQ 的本地聊天记录),服务器仅传输关键数据(如游戏同步信息、聊天消息);
- 适用场景:对功能、性能要求高的场景(如大型游戏、企业 OA 系统)。
2. B/S 模型(浏览器 / 服务器模型)
- 定义:是 C/S 的特殊形式,客户端为 “通用浏览器”(如 Chrome、Edge),无需安装额外软件,服务器提供 HTTP/HTTPS 服务;承担全部资源存储与处理,是当前互联网主流架构。
- 核心特点(与 C/S 对比):
对比维度 | C/S 模型 | B/S 模型 |
---|---|---|
客户端形态 | 专用客户端,需安装,适配成本高 | 通用浏览器,无需安装,“一次开发多端兼容” |
依赖协议 | 可自定义协议或使用 FTP 等标准协议 | 强依赖 HTTP/HTTPS(长连接用 WebSocket) |
资源分布 | 客户端存静态资源,服务器存动态资源 | 服务器存全部资源,浏览器仅临时缓存(Cookie) |
- 适用场景:轻量型、跨平台需求场景,如网页版工具(在线文档 Google Docs)、信息展示类网站(新闻网站、电商网站)、企业轻量办公系统(网页版考勤系统)、临时使用服务(在线问卷调查)。
3. P2P 模型(点对点模型)
- 定义:“去中心化” 架构,所有节点(Peer)地位平等,既可作为 “客户端” 请求资源,也可作为 “服务器” 提供资源,节点间直接通信,无需依赖中心服务器(仅可选 “Tracker 服务器” 辅助节点发现)。
- 核心特点:
- 架构:无中心节点,单个节点下线不影响整体网络,抗故障能力强;
- 资源分布:分布式存储,文件拆分为多个片段(如 BT 下载拆分为 256KB 片段),分散存储在不同节点,下载时从多节点并行获取;
- 扩展性:节点越多,提供资源的 “种子” 越多,下载速度越快(与 C/S 相反,C/S 节点多会增加服务器压力);
- 技术难点:需解决 “NAT 穿透”(内网节点无法被外网直接访问,需 STUN/TURN 技术)、“节点信誉”(防范恶意节点提供错误数据);
- 适用场景:大文件共享(BT 下载、迅雷 P2P 加速)、实时通信(WebRTC 网页版视频会议)、分布式计算(区块链网络、科学计算项目 SETI@home)。