Unix Socket 和 TCP/IP Socker
🧱 一、通信机制区别
项目 | Unix Domain Socket | TCP/IP Socket |
---|---|---|
通信类型 | 本地通信(同一台主机) | 网络通信(本地或远程) |
传输协议 | 使用文件系统路径作为地址标识,无需 IP 和端口 | 使用 IP 和端口作为地址标识 |
协议栈 | 不走网络协议栈,直接通过内核内存传输 | 走完整的网络协议栈(如 TCP/IP) |
性能 | 非常高(少了协议栈开销) | 相对较低(协议栈处理、数据封包解析) |
🚀 二、使用场景区别
项目 | Unix Domain Socket | TCP/IP Socket |
---|---|---|
适用场景 | 本地进程间通信(IPC)如 Nginx 和 PHP-FPM | 跨主机通信,如客户端与远程服务器通信 |
典型使用 | Docker 容器内部通信、数据库本地连接(如 PostgreSQL) | Web服务、分布式系统通信 |
🔒 三、安全与部署区别
项目 | Unix Domain Socket | TCP/IP Socket |
---|---|---|
访问控制 | 可通过文件权限控制(如 /tmp/socket.sock ) |
需要配置防火墙、监听地址来限制访问 |
部署复杂度 | 简单(仅需要指定文件路径) | 需要监听 IP、配置端口、防火墙、安全策略 |
📊 四、开发对比
项目 | Unix Domain Socket | TCP/IP Socket |
---|---|---|
地址结构 | sockaddr_un (指定路径) |
sockaddr_in (指定 IP+端口) |
开发接口 | socket()、bind()、listen()、accept() 相同,只是地址结构不同 |
同上 |
调试工具 | 一般看不到流量(不走网络),可以用 lsof 查看 |
可以用 tcpdump 、netstat 、wireshark 抓包分析 |
✅ 总结一句话
- 如果 两个进程在同一台机器上通信,选 Unix Domain Socket,速度快、安全性高。
- 如果 需要跨主机通信,只能用 TCP/IP Socket。
🧠 五、Unix Domain Socket 的通信原理
📌 核心原理:内核空间内存拷贝 + 内存队列(socket buffer)
- 不经过网络协议栈(TCP/IP)
- 数据在两个进程之间传递时,完全在本机内核中完成,不走网卡、不封包、不路由。
- 使用内核的 Socket 缓冲区
- 类似于一对管道:每个 Unix socket 对应一对缓存队列(send buffer 和 recv buffer)。
- 发送方
write()
数据,内核拷贝到 socket buffer; - 接收方
read()
时,从 buffer 中取出数据。
- 拷贝次数
- 默认是两次拷贝:
- 用户态 → 内核态(write)
- 内核态 → 用户态(read)
- Zero-Copy(零拷贝)优化:
- 某些新版本内核可对 Unix Socket 开启“零拷贝”优化(比如
splice
),进一步提升性能。
- 某些新版本内核可对 Unix Socket 开启“零拷贝”优化(比如
- 效率优势
- 由于无需封包、校验、序列号等操作,速度非常快,延迟非常低。
✅ 总结:Unix Domain Socket 本质是借助内核的内存机制实现本地进程通信,效率高、延迟低。
🌐 六、TCP/IP Socket 的通信原理
📌 核心原理:走完整 TCP/IP 协议栈 + 网络缓冲区 + 可能跨主机
- 协议栈处理
- 发送数据时:
- 用户态 → 内核态 → TCP层 → IP层 → 网卡驱动 → 发送到网络
- 接收数据时:
- 网卡接收 → IP层 → TCP层 → socket buffer → 用户态读取
- 封包与校验
- 每个数据包要加上 TCP 头、IP 头、进行序列号管理、重传机制等;
- TCP 的三次握手、流控、拥塞控制等都在这里进行。
- 拷贝次数
- 通常至少两次(可能更多):
- 用户态 → 内核态(write)
- 内核态 → 用户态(read)
- 还有网卡 DMA 的硬件拷贝过程。
- 可能的网络瓶颈
- 网络延迟、丢包重传、带宽限制都会影响通信效率。
✅ 总结:TCP/IP Socket 适用于跨主机通信,但由于协议栈和网络环境,效率远不如 Unix Socket。
🚩 一句话对比总结
项目 | Unix Domain Socket | TCP/IP Socket |
---|---|---|
是否跨主机 | ❌ 本地进程间 | ✅ 可跨主机 |
数据路径 | 用户态 → 内核态(内核内存传递) | 用户态 → 内核态 → 协议栈 → 网卡/网络 |
协议栈处理 | ❌ 无 | ✅ 有(TCP/IP) |
拷贝次数 | 通常 2 次(或 0 拷贝) | 通常 2 次(加协议处理) |
效率 | ✅ 极高 | ❌ 较低 |
这是 Unix Domain Socket 和 TCP/IP Socket 的数据传输流程图,并配套一个简单的 Python 示例对照两种通信方式。
🖼️ 流程图说明
左边为 Unix Domain Socket:
- 数据从应用层通过
write()
进入内核的 socket buffer - 另一端
read()
直接读取,整个过程在内核中完成,不走网络
右边为 TCP/IP Socket:
- 数据需经过 TCP/IP 协议栈处理,经过网卡、可能传输到远程机器
- 中间涉及封包、路由、流控等多个阶段
👉 图像展示了用户态和内核态之间的清晰数据路径对比。
🧪 Python 示例
下面分别演示 Unix Domain Socket 和 TCP/IP Socket 的基本用法。
✅ 1. Unix Domain Socket 示例(本地通信)
1 |
|
✅ 2. TCP/IP Socket 示例(网络通信)
1 |
|
这两段代码逻辑一样,只是使用的 socket 类型不同(AF_UNIX
vs AF_INET
),你可以实际跑一下对比差异(如 CPU 使用率、延迟等)。
如果你还想深入了解“零拷贝优化”或者“进程间通信对比”,我也可以继续补充~
Unix Socket 和 TCP/IP Socker
https://luffy997.github.io/2025/04/09/Unix-Socket-和-TCP-IP-Socker/