UNIX域套接字(Unix Domain Sockets, UDS) 的两种接口

目录

    • [1. 流式套接字(SOCK_STREAM)](#1. 流式套接字(SOCK_STREAM))
    • [2. 数据报套接字(SOCK_DGRAM)](#2. 数据报套接字(SOCK_DGRAM))
    • [3. 两者的核心区别对比](#3. 两者的核心区别对比)
    • [4. 为什么 UNIX 域套接字的数据报是"不可靠"的?](#4. 为什么 UNIX 域套接字的数据报是“不可靠”的?)
    • [5. 如何选择?](#5. 如何选择?)
    • [6. 补充:文件描述符传递(仅流式套接字支持)](#6. 补充:文件描述符传递(仅流式套接字支持))
    • 总结

1. 流式套接字(SOCK_STREAM)

特点

  • 面向连接:在通信前需要建立一个"连接",类似于打电话前需要拨通电话。
  • 可靠传输:数据不会丢失、重复或乱序,内核会确保数据按顺序到达。
  • 字节流(Byte Stream):数据以连续的字节流形式传输,没有消息边界。例如,发送方发送的3条消息可能被接收方一次性读取为一个长字节流,需要应用程序自行解析分隔。
  • 全双工:支持双向通信,双方可以同时发送和接收数据。

类比

  • 类似 TCP 协议:因为 TCP 也是面向连接、可靠、字节流的。
  • 比如:两个人通过电话聊天,通话过程中不会丢失任何一句话,且按顺序接收。

典型使用场景

  • 数据库通信:例如 MySQL 使用 UDS 流式套接字与客户端通信,确保 SQL 查询和结果的可靠性。
  • 进程间长连接服务:如 Web 服务器与后端服务的稳定通信。

代码示例(伪代码)

c 复制代码
// 创建流式套接字(SOCK_STREAM)
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

// 服务器端需要绑定地址并监听
bind(sockfd, &address, sizeof(address));
listen(sockfd, 5);
int client_sock = accept(sockfd, ...);  // 建立连接后获得客户端套接字

// 客户端需要主动连接
connect(sockfd, &server_address, sizeof(server_address));
send(client_sock, "Hello", 5, 0);      // 发送数据流

2. 数据报套接字(SOCK_DGRAM)

特点

  • 无连接:不需要预先建立连接,直接发送数据,类似于寄信。
  • 不可靠传输:数据可能丢失、重复或乱序,内核不保证送达。
  • 消息边界(Message-Oriented):每条消息是独立的,接收方能识别每条消息的边界。例如,发送3条消息,接收方会收到3次独立的数据包。
  • 全双工:同样支持双向通信,但每次通信是独立的消息。

类比

  • 类似 UDP 协议:因为 UDP 也是无连接、不可靠、基于消息的。
  • 比如:寄三封信给朋友,可能其中一封信丢失,或者收到顺序被打乱。

典型使用场景

  • 日志记录系统:可以容忍少量日志丢失,但需要快速发送。
  • 实时性要求高的场景:例如游戏服务器的简单状态更新,避免因重传延迟。

代码示例(伪代码)

c 复制代码
// 创建数据报套接字(SOCK_DGRAM)
int sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);

// 服务器端绑定地址即可,无需监听和 accept
bind(sockfd, &server_address, sizeof(server_address));

// 客户端无需 connect,可以直接发送(但通常先 bind 自己的地址)
sendto(sockfd, "Hello", 5, 0, &server_address, sizeof(server_address));

// 接收数据时需要指定接收缓冲区和地址
recvfrom(sockfd, buffer, 1024, 0, &client_address, &addr_len);

3. 两者的核心区别对比

特性 流式套接字(SOCK_STREAM) 数据报套接字(SOCK_DGRAM)
连接方式 面向连接(需先建立连接) 无连接(直接发送数据)
可靠性 可靠(数据不丢失、不重复、不乱序) 不可靠(可能丢失、重复、乱序)
数据传输形式 字节流(无消息边界) 消息(有消息边界,每条独立)
速度 略慢(需维护连接状态) 更快(无需维护连接)
是否需要 bind 服务端必须 bind,客户端可选 客户端和服务器都需要 bind 地址
典型协议类比 TCP UDP

4. 为什么 UNIX 域套接字的数据报是"不可靠"的?

虽然 UNIX 域套接字在本地通信,但 数据报模式(SOCK_DGRAM)仍然是不可靠的。原因如下:

  • 设计一致性:为了与 UDP 的行为保持一致,方便跨网络和本地套接字的代码迁移。
  • 内核实现 :虽然本地传输的可靠性很高,但内核不会主动保证数据报的送达,例如:
    • 如果接收方未准备好(如未调用 recv),可能会丢弃数据。
    • 内存不足时可能导致数据丢失。

5. 如何选择?

  • 选流式套接字(SOCK_STREAM)如果:

    • 需要可靠传输(如金融交易、数据库操作)。
    • 需要保持数据顺序。
    • 需要长连接,减少重复建立连接的开销。
  • 选数据报套接字(SOCK_DGRAM)如果:

    • 速度比可靠性更重要(如实时游戏、日志传输)。
    • 每条消息是独立的,可以容忍少量丢失。
    • 需要无连接的简单通信(如偶尔发送指令)。

6. 补充:文件描述符传递(仅流式套接字支持)

UNIX 域套接字的流式套接字支持 传递文件描述符(File Descriptor Passing),这是其独特优势。例如:

  • 一个进程可以将打开的文件描述符(如文件句柄、网络套接字)传递给另一个进程,接收方可以直接使用该描述符操作资源。
  • 这种功能在进程间共享资源时非常高效,例如 Web 服务器将客户端连接传递给 worker 进程。

总结

  • 流式套接字(SOCK_STREAM):像一条稳定的管道,保证数据可靠、有序地流动,适合需要稳定通信的场景。
  • 数据报套接字(SOCK_DGRAM):像快递服务,快速发送独立包裹,但可能丢失或乱序,适合对速度要求高的场景。
相关推荐
小辰记事本6 小时前
从零读懂RoCEv2数据包构造:从WQE到线缆上的完整旅程
服务器·网络·网络协议·rdma
江公望10 小时前
Ubuntu htop命令,10分钟讲清楚
linux·服务器
哎呦,帅小伙哦10 小时前
Linux 时间:从原子钟到 clock_gettime 的每一面
linux·运维·服务器
张小姐的猫10 小时前
【Linux】多线程 —— 线程互斥
linux·运维·服务器·c++
YuanDaima204811 小时前
Linux 进阶运维与 AI 环境实战:进程管理、网络排错与 GPU 监控
linux·运维·服务器·网络·人工智能
lolo大魔王12 小时前
Linux 数据文件处理实战:排序、搜索、压缩、归档一站式详解
linux·运维·服务器
1892280486112 小时前
NY382固态MT29F32T08GSLBHL8-24QM:B
大数据·服务器·人工智能·科技·缓存
xhbh66613 小时前
网关端口映射和路由器端口转发有什么区别?配置要点全解析
运维·服务器·网络·智能路由器·端口映射·映射·无痕网关
STDD13 小时前
Soulmask《灵魂面具》 专用服务器搭建教程
运维·服务器·github
半壶清水13 小时前
用P4 Tutorial、BMv2 和 Mininet‌解析网络第一集------模拟环境搭建
运维·服务器·网络·网络协议·tcp/ip