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 查看 可以用 tcpdumpnetstatwireshark 抓包分析

✅ 总结一句话

  • 如果 两个进程在同一台机器上通信,选 Unix Domain Socket,速度快、安全性高。
  • 如果 需要跨主机通信,只能用 TCP/IP Socket

🧠 五、Unix Domain Socket 的通信原理

📌 核心原理:内核空间内存拷贝 + 内存队列(socket buffer)

  1. 不经过网络协议栈(TCP/IP)
    • 数据在两个进程之间传递时,完全在本机内核中完成,不走网卡、不封包、不路由。
  1. 使用内核的 Socket 缓冲区
    • 类似于一对管道:每个 Unix socket 对应一对缓存队列(send buffer 和 recv buffer)。
    • 发送方 write() 数据,内核拷贝到 socket buffer;
    • 接收方 read() 时,从 buffer 中取出数据。
  1. 拷贝次数
    • 默认是两次拷贝:
      • 用户态 → 内核态(write)
      • 内核态 → 用户态(read)
  1. Zero-Copy(零拷贝)优化:
    • 某些新版本内核可对 Unix Socket 开启“零拷贝”优化(比如 splice),进一步提升性能。
  1. 效率优势
    • 由于无需封包、校验、序列号等操作,速度非常快,延迟非常低。

✅ 总结:Unix Domain Socket 本质是借助内核的内存机制实现本地进程通信,效率高、延迟低。


🌐 六、TCP/IP Socket 的通信原理

📌 核心原理:走完整 TCP/IP 协议栈 + 网络缓冲区 + 可能跨主机

  1. 协议栈处理
    • 发送数据时:
      • 用户态 → 内核态 → TCP层 → IP层 → 网卡驱动 → 发送到网络
    • 接收数据时:
      • 网卡接收 → IP层 → TCP层 → socket buffer → 用户态读取
  1. 封包与校验
    • 每个数据包要加上 TCP 头、IP 头、进行序列号管理、重传机制等;
    • TCP 的三次握手、流控、拥塞控制等都在这里进行。
  1. 拷贝次数
    • 通常至少两次(可能更多):
      • 用户态 → 内核态(write)
      • 内核态 → 用户态(read)
    • 还有网卡 DMA 的硬件拷贝过程。
  1. 可能的网络瓶颈
    • 网络延迟、丢包重传、带宽限制都会影响通信效率。

✅ 总结:TCP/IP Socket 适用于跨主机通信,但由于协议栈和网络环境,效率远不如 Unix Socket。


🚩 一句话对比总结

项目 Unix Domain Socket TCP/IP Socket
是否跨主机 ❌ 本地进程间 ✅ 可跨主机
数据路径 用户态 → 内核态(内核内存传递) 用户态 → 内核态 → 协议栈 → 网卡/网络
协议栈处理 ❌ 无 ✅ 有(TCP/IP)
拷贝次数 通常 2 次(或 0 拷贝) 通常 2 次(加协议处理)
效率 ✅ 极高 ❌ 较低

pEHYPne.md.png
这是 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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# server_unix.py
import socket
import os

SOCKET_PATH = "/tmp/demo_socket"

if os.path.exists(SOCKET_PATH):
os.remove(SOCKET_PATH)

server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server.bind(SOCKET_PATH)
server.listen(1)
conn, _ = server.accept()

data = conn.recv(1024)
print("收到:", data.decode())
conn.send(b"你好,客户端!")
conn.close()
server.close()
# client_unix.py
import socket

SOCKET_PATH = "/tmp/demo_socket"

client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect(SOCKET_PATH)
client.send(b"你好,服务端!")
data = client.recv(1024)
print("收到:", data.decode())
client.close()

✅ 2. TCP/IP Socket 示例(网络通信)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# server_tcp.py
import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 8888))
server.listen(1)
conn, addr = server.accept()

data = conn.recv(1024)
print("收到:", data.decode())
conn.send(b"你好,TCP客户端!")
conn.close()
server.close()
# client_tcp.py
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8888))
client.send(b"你好,TCP服务端!")
data = client.recv(1024)
print("收到:", data.decode())
client.close()

这两段代码逻辑一样,只是使用的 socket 类型不同(AF_UNIX vs AF_INET),你可以实际跑一下对比差异(如 CPU 使用率、延迟等)。

如果你还想深入了解“零拷贝优化”或者“进程间通信对比”,我也可以继续补充~


Unix Socket 和 TCP/IP Socker
https://luffy997.github.io/2025/04/09/Unix-Socket-和-TCP-IP-Socker/
作者
Luffy997
发布于
2025年4月9日
许可协议