当前位置: 首页 > news >正文

linu 网络 :TCP粘包及UDP

一、TCP 粘包问题(续上一节)

1. 粘包本质

核心原因具体表现
TCP 是字节流协议,无天然消息边界发送端:多个小消息被合并成一个 TCP 段(Nagle 算法优化)
内核缓冲区(发送 / 接收)暂存数据接收端:多个 TCP 段数据被合并,一次性交给应用层

2. 应用层解决思路

解决方案核心逻辑适用场景优缺点
特殊字符边界每个消息末尾加固定标记(如\r\n),接收端按标记拆分文本类数据(如 HTTP 协议)优点:实现简单;缺点:消息含标记时易误拆分
定长消息约定固定消息长度(如 100 字节),不足补空,接收端按固定长度读取数据长度固定场景(如传感器数据)优点:逻辑简单;缺点:长度不固定时浪费带宽
自定义结构体协议设计 “消息头 + 消息体”,头中含消息体长度(如type字段标识长度 / 类型)复杂数据(文件、二进制数据)优点:灵活无歧义;缺点:需两端协议兼容

二、TCP 编程(C/S 模型)

1. 核心 API 对比

API 类型函数原型关键差异适用场景
标准 IO 函数read(int fd, void *buf, size_t len)
write(int fd, const void *buf, size_t len)
无额外标志,仅支持阻塞通用 IO 操作(含 socket)
Socket 专用函数recv(int sockfd, void *buf, size_t len, int flags)
send(int sockfd, const void *buf, size_t len, int flags)
支持MSG_DONTWAIT(非阻塞)需控制读写模式的 socket 场景

2. 客户端与服务器流程对比

角色核心步骤关键说明
TCP 客户端1. socket():创建 TCP socket
2. (可选)bind():绑定客户端地址(通常系统自动分配)
3. connect():连接服务器(必须成功后通信)
4. send()/recv():数据交互(需处理粘包)
5. close():关闭 socket
依赖connect()建立连接,无连接则无法通信
TCP 服务器1. socket():创建 TCP socket
2. bind():绑定固定端口(客户端需知道该端口)
3. listen():开启监听(设置监听队列长度)
4. accept():接收客户端连接(返回新通信 socket)
5. send()/recv():通过新 socket 交互
6. close():关闭通信 socket 和监听 socket
listenfd仅用于监听,connfd用于实际通信

3. 常见场景实现

场景核心技术注意事项
点对点聊天多线程 / 多进程:
- 线程 1:读键盘→send()
- 线程 2:recv()→打印
线程需pthread_join()/pthread_detach()回收资源
文件传输自定义结构体协议:
- 步骤 1:发文件名(type=-1
- 步骤 2:循环发文件数据(type=数据长度
- 步骤 3:发结束标志(type=0
需处理文件读写错误(如read()返回 0 表示文件结束)

三、UDP 编程核心(C/S 模型)

1. UDP 协议核心特点

特点具体说明影响
无连接无需connect(),直接通过sendto()指定目标地址通信灵活,但需每次发送时携带目标地址
不可靠不保证数据送达、不保证顺序、不重传适合实时场景(如视频),不适合需可靠传输的场景(如文件)
数据报每个sendto()对应一个完整消息,recvfrom()一次读一个无粘包问题,无需额外处理消息边界

2. 核心 API(sendto/recvfrom)

函数原型关键参数说明
sendtossize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)dest_addr:目标地址(客户端→服务器需填服务器地址)
recvfromssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)src_addr:保存发送方地址;addrlen需先初始化(值结果参数)

3. 客户端与服务器流程对比

角色核心步骤关键说明
UDP 客户端1. socket():创建 UDP socket
2. (可选)bind():绑定客户端地址
3. sendto():指定服务器地址发送数据
4. recvfrom():接收服务器回发
5. close():关闭 socket
无需连接,直接发送;需提前知道服务器 IP 和端口
UDP 服务器1. socket():创建 UDP socket
2. bind():绑定固定端口(必须,客户端需定位)
3. recvfrom():接收客户端数据(获取客户端地址)
4. sendto():通过客户端地址回发数据
5. close():关闭 socket
依赖bind()固定端口,否则客户端无法找到服务器

四、TCP 与 UDP 核心差异对比

对比维度TCPUDP
连接方式面向连接(需connect无连接(直接sendto
数据格式字节流(易粘包,需应用层处理边界)数据报(无粘包,天然消息边界)
可靠性可靠(确认、重传、有序)不可靠(无确认、无重传)
效率低(连接建立、确认机制耗时)高(无额外开销,实时性好)
编程重点处理粘包、连接管理、资源回收处理地址(sendto/recvfrom)、丢包应对
典型应用文件传输、聊天、HTTP/HTTPS
http://www.dtcms.com/a/355356.html

相关文章:

  • 软件设计师备考-(五)计算机网络
  • 客户端是否都需要主动发送`FindService`报文来寻找服务
  • FPGA开发技能(12)matlab图片处理助力FPGA开发
  • 【温室气体数据集】GlobalView 数据概述
  • Kotlin 协程之Channel 的高阶应用
  • RAGFlow
  • plantsimulation知识点 一条轨道上多台RGV如何引用
  • 【Big Data】Presto db 一种语言、一个接口搭建可靠、高效数据湖仓
  • NineData 最新发布 SQL Server 双向实时同步功能
  • 手机上访问你电脑上的前端项目
  • Rust 登堂 之 类型转换(三)
  • 趣味学Rust基础篇(数据类型)
  • Python Discord Logo
  • 【SpringAI】快速上手,详解项目快速集成主流大模型DeepSeek,ChatGPT
  • 操作系统-基础知识面试常见篇
  • 算法之排序
  • java后端的各种注解
  • 基于 PyTorch 构建 Dataset 与 DataLoader:从 TXT 文件读取到新增类别全流程指南
  • AI大模型企业落地指南-笔记02
  • Spring 框架中事务传播行为的定义
  • 146. LRU缓存
  • python使用sqlcipher4对sqlite数据库加密
  • 【论文阅读】基于人工智能的下肢外骨骼辅助康复方法研究综述
  • 【电源专题】隐形守护者:防爆锂电池如何守护高危环境的安全防线
  • UE5提升分辨率和帧率的方法
  • 网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
  • Leetcode 深度优先搜索 (15)
  • 【大前端】React Native(RN)跨端的原理
  • 比较两个字符串的大小
  • 使用CDN后如何才不暴露IP