当前位置: 首页 > 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.xdnf.cn/news/1380835.html

相关文章:

  • 【C++】C++11的右值引用和移动语义
  • STAGEWISE实战指南:从集成到使用的完整解决方案
  • vscode pyqt5设置
  • 【ai编辑器】使用cursor-vip获得cursor的pro版 pro plan(mac)
  • uniapp vue3 canvas实现手写签名
  • Flask测试平台开发,登陆重构
  • (二分查找)Leetcode34. 在排序数组中查找元素的第一个和最后一个位置+74. 搜索二维矩阵
  • 并发编程——05 并发锁机制之深入理解synchronized
  • 学习数据结构(13)二叉树链式结构下
  • 线程池及线程池单例模式
  • 带动态条件的模糊查询SQL
  • DINOv2 vs DINOv3 vs CLIP:自监督视觉模型的演进与可视化对比
  • LeetCode 3446. 按对角线进行矩阵排序
  • UE5提升分辨率和帧率的方法
  • 搭建私有云3步法:cpolar简化Puter本地云端配置
  • C# SIMD编程实践:工业数据处理性能优化案例
  • C++ 哈希概念版
  • 【实战笔记】OCI Ubuntu 24.04 + TigerVNC + XFCE + Chrome 开机自启全记录
  • 错误模块路径: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
  • 从卡顿到丝滑:大型前端项目 CSS 优化全攻略
  • [高并发系统设计] - 搭建高并发高可用的系统 - 学习与探究
  • 【大前端】React useEffect 详解:从入门到进阶
  • Shi-Tomasi 算法和 Harris 角点检测算法都是经典的角点检测方法,但它们在理论基础和实现细节上有一些区别。下面我将详细对比这两种算法。
  • List<Map<String, String>>最简单的遍历方式
  • 【传奇开心果系列】Flet框架带图标带交互动画的办公用品费用占比统计饼图自定义模板
  • GitHub 热榜项目 - 日榜(2025-08-28)
  • 达梦数据库-重做日志文件(一)
  • 云计算学习100天-第30天
  • 09- AI大模型-docker部署dify以及 dify的使用案例:公司智能助手(构建知识库)(上篇)
  • TDengine 数据订阅支持 MQTT 协议用户手册