网络通信与协议栈 -- OSI,TCP/IP模型,协议族,UDP编程

发布于:2025-09-04 ⋅ 阅读:(24) ⋅ 点赞:(0)

网络通信的核心是实现不同主机上进程间的数据交换,其技术体系围绕 “协议分层模型” 展开,向下依赖硬件介质传输电 / 光信号,向上支撑各类网络应用(如网页浏览、文件传输)。本文结合 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()返回的套接字ID
    • my_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:本地套接字ID
    • buf:发送数据缓冲区
    • 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:本地套接字ID
    • buf:接收数据缓冲区
    • 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");  // 服务器IP

  int 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)。

网站公告

今日签到

点亮在社区的每一天
去签到