
🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平
🎬 艾莉丝的简介:

文章目录
- [1 ~> 总结](#1 ~> 总结)
- [2 ~> 思维导图](#2 ~> 思维导图)
- [3 ~> 剖析概念](#3 ~> 剖析概念)
-
- [3.1 TCP 数据从 A 到 B 完整流程](#3.1 TCP 数据从 A 到 B 完整流程)
-
- [3.1.1 发送端:应用层→内核态](#3.1.1 发送端:应用层→内核态)
-
- 1、序列化
- [2、write 系统调用](#2、write 系统调用)
- [3.1.2 传输阶段:内核 & 网络](#3.1.2 传输阶段:内核 & 网络)
- [3.1.3 接收端:内核态→应用层](#3.1.3 接收端:内核态→应用层)
- [3.2 四条核心结论](#3.2 四条核心结论)
- [3.3 TCP 字节流核心特性与问题](#3.3 TCP 字节流核心特性与问题)
- [3.4 对比](#3.4 对比)
- [4 ~> 关键问题与答案](#4 ~> 关键问题与答案)
-
- [4.1 问题 1:为什么说 "网络 I/O 的本质是拷贝"?](#4.1 问题 1:为什么说 “网络 I/O 的本质是拷贝”?)
- [4.2 问题 2:TCP 的 "全双工" 是如何实现的?](#4.2 问题 2:TCP 的 “全双工” 是如何实现的?)
- [4.3 问题 3:为什么 TCP 一定会出现粘包?如何解决?](#4.3 问题 3:为什么 TCP 一定会出现粘包?如何解决?)
- 结尾

1 ~> 总结
本文核心讲解Linux 下 TCP 网络 I/O 的本质 :数据从主机 A 到主机 B 必须经过应用层序列化→用户态拷贝到内核发送缓冲区→内核协议栈传输→拷贝到对端内核接收缓冲区→应用层反序列化 的完整流程;网络 I/O 本质是内存拷贝,TCP 全双工 依靠一对收发缓冲区实现,面向字节流 会引发粘包问题,必须通过应用层自定义协议 + 序列化 / 反序列化保证报文完整性。
2 ~> 思维导图

3 ~> 剖析概念
3.1 TCP 数据从 A 到 B 完整流程
3.1.1 发送端:应用层→内核态
1、序列化
将应用层结构化数据(昵称、消息、时间)转为连续字符串 / 二进制流。
2、write 系统调用
数据从用户态缓冲区拷贝到内核 TCP 发送缓冲区,拷贝完成即返回,不代表发到网络。
3.1.2 传输阶段:内核 & 网络
1、内核按TCP 滑动窗口、拥塞控制 封装报文。
2、经由网络层、链路层发出。
3、红色虚线:数据流向;蓝色虚线:ACK / 回传数据(全双工)。
3.1.3 接收端:内核态→应用层
-
1、数据先存入内核 TCP 接收缓冲区。
-
2、read 系统调用
- 数据从内核接收缓冲区 拷贝到用户态缓冲区。
-
3、反序列化
- 按约定协议解析回结构化数据(消息、时间、昵称)。
3.2 四条核心结论
- 1、write 的本质不是发送到网络,而是拷贝到内核发送缓冲区。
- 2、应用层收发数据本质都是拷贝函数。
- 3、网络发送本质:将发送端 OS 的 TCP 发送缓冲区 → 拷贝到接收端 OS 的 TCP 接收缓冲区。
- 4、TCP 全双工本质:一个 sockfd 对应一对独立的发送 / 接收缓冲区。
3.3 TCP 字节流核心特性与问题
1、核心特性
- TCP 是面向字节流协议,不维护消息边界。
- write 次数 ≠ read 次数,不保证一一对应。
- 数据完整性由应用层保证,TCP 不保证。
2、粘包问题
- 现象:一次 read 读到多条消息 或不完整消息。
- 原因:字节流无边界,内核按缓冲区大小收发。
- 后果:直接处理会导致数据解析错误。
将来字符串实现了少读或者多读,这就是面向字节流的"粘包问题"。
读取的次数和写的次数并不是一比一完全一样的;面向数据报是一比一对应的,面向字节流不一定。
面向字节流,在TCP那里不关心什么变量、整型、字符、字符串什么的。读上来的时候报文不一定是完整的,完整性需要由应用层来保证,TCP不保证。
发送的权利是OS(TCP)自主决定的。
我们字符串少读或者多读,就是面向字节流导致的
粘包问题。读取的次数和写的次数并不是一比一完全一样的。
但是面向字节流读取的时候,TCP本身并不关心本身发送的数据是什么,我们对应的TCP没有什么字符,字符串,变量。在我这里都是一个个字节,所以TCP是面向字节流,不对报文完整性负责,需要应用层保证。
3、解决方案
- 序列化 + 反序列化
- 应用层自定义协议(长度字段、分隔符、固定长度)
3.4 对比
| 对比项 | 关键说明 |
|---|---|
| I/O 本质 | 内存拷贝,不是直接操作网卡 |
| write 成功 | 仅拷贝到内核缓冲区,不代表对方收到 |
| read 成功 | 从内核缓冲区拷贝到用户态 |
| TCP 全双工 | 一个 sockfd 包含 send/recv 两个独立缓冲区 |
| 粘包原因 | TCP 面向字节流,无消息边界 |
| 完整性保证 | 必须由应用层协议实现 |
4 ~> 关键问题与答案
4.1 问题 1:为什么说 "网络 I/O 的本质是拷贝"?
答案: 应用层不能直接访问网卡与内核协议栈;write/read/send/recv都是把数据在用户态缓冲区 和内核态 TCP 缓冲区之间拷贝;跨主机传输本质是一端内核缓冲区拷贝到另一端内核缓冲区,全程都是内存拷贝。
4.2 问题 2:TCP 的 "全双工" 是如何实现的?
答案: 一个 TCP 套接字sockfd在内核中对应两个独立缓冲区 【发送缓冲区 (send buffer)、接收缓冲区 (recv buffer)】,读写互不阻塞、可同时进行,因此支持全双工通信。
4.3 问题 3:为什么 TCP 一定会出现粘包?如何解决?
答案:
- 原因 :TCP 是面向字节流 协议,没有消息边界,多次
write的数据可能被一次read读完,或一次write被多次read读取。 - 解决 :必须在应用层做序列化 / 反序列化 ,并通过自定义协议(长度头、分隔符、固定包长)确定消息边界,保证报文完整解析。
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!"
"技术之路难免有困惑,但同行的人会让前进更有方向。" |
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!
往期回顾:
【Linux网络】Linux 网络编程入门:TCP Socket 编程(下)
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა
