• 首页
  • 搜索
  • 工具
  • 分类
  • 日志
  • 友链
  • 图片

It's Geek KingYoungy

KEEP CHALLENGE
多进程/多线程并发编程

Unix Domain Socket 编程:字节流与数据报套接字详解

2025-03-26 浏览量 117 暂无评论

Unix Domain Socket 编程:字节流与数据报套接字详解


一、字节流套接字(SOCK_STREAM)

1. 核心特性

• 可靠传输:提供类似 TCP 的有序、无丢失数据流,无记录边界。
• 全双工通信:支持双向数据传输,需通过 listen()/accept() 建立连接。
• 适用场景:需高可靠性的连续数据交互(如文件传输、RPC 服务)。

2. 核心系统调用

(1)socket() 创建套接字

int socket(int domain, int type, int protocol);

• 参数:
• domain:必须为 AF_UNIX 或 AF_LOCAL。
• type:设为 SOCK_STREAM。
• protocol:固定为 0。
• 返回值:成功返回文件描述符,失败返回 -1(如 EPROTONOSUPPORT 协议不支持)。

(2)bind() 绑定地址

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

• 地址结构:

struct sockaddr_un {
    sa_family_t sun_family;    // AF_UNIX
    char sun_path[108];        // 文件路径或抽象名称
};

• 路径类型:
• 普通路径:如 /tmp/mysocket.sock,需确保路径可写且无冲突。
• 抽象命名空间(Linux 特有):sun_path[0] = '\0',后续字符为抽象名(无需文件实体)。
• addrlen 计算:offsetof(struct sockaddr_un, sun_path) + strlen(name)(抽象名需 +1)。

(3)listen() 监听队列

int listen(int sockfd, int backlog);

• backlog:最大等待连接数,建议设为 SOMAXCONN。
• 错误处理:若队列满,后续连接请求直接返回 ECONNREFUSED。

(4)accept() 接收连接

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

• addr 参数:通常设为 NULL(客户端地址无意义)。
• 返回值:新套接字描述符专用于该连接。

(5)数据传输

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

• flags 标志:
• MSG_OOB:带外数据(需双方支持)。
• MSG_DONTWAIT:非阻塞模式。


二、数据报套接字(SOCK_DGRAM)

1. 核心特性

• 保留消息边界:每次 send() 对应一次 recv(),数据按报文独立接收。
• 无连接特性:无需建立连接,可直接发送数据。
• 可靠性:数据不丢失但无序(与 UDP 不同,Unix 域数据报本身可靠)。
• 适用场景:日志传输、实时状态广播等低延迟场景。

2. 核心系统调用

(1)socket() 创建套接字

int socket(int domain, int type, int protocol);

• type:设为 SOCK_DGRAM。

(2)bind() 绑定地址

• 地址规则:同字节流套接字,但允许同一地址被多次绑定(需设置 SO_REUSEADDR)。

(3)直接数据收发

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);

• dest_addr:目标地址(必须已绑定)。
• src_addr:接收时可获取发送方地址。

(4)连接模式(可选)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

• 作用:绑定默认目标地址,后续可使用 send()/recv()以及write()/read()。


三、Linux 抽象 Socket 名空间(跨进程通用)

1. 实现方式

• 命名规则:sun_path[0] = '\0',后续字符为抽象名(如 \0myapp)。
• 优势:
• 无文件系统依赖,避免路径权限问题。
• 进程退出后自动释放,无需手动清理。

2. 系统查询

ss -x -a | grep '@'        # 查看活跃抽象套接字
cat /proc/net/unix         # 内核级列表(含 inode 和权限)

四、进阶功能对比

特性字节流套接字数据报套接字
连接管理需 listen()/accept()无连接
记录边界无边界(连续流)保留边界
最大消息长度无限制受限于内核缓冲区(通常 130KB)
描述符传递支持 (sendmsg())支持 (sendmsg())
凭证传递支持(SO_PASSCRED)支持(SO_PASSCRED)

五、总结

字节流套接字适用于需要可靠连续数据流的场景(如数据库连接),而数据报套接字更适合短消息、无连接交互。Linux 抽象命名空间通过消除文件依赖提升了安全性和便捷性,尤其在容器化环境中优势显著。开发者应根据业务需求选择通信模式,并注意两者的系统调用差异。

文件锁技术详解:flock与fcntl系统调用
C语言结构体/共用体的赋值限制

评论

  • 文章目录
  • 站点概览
    author

    38 日志
    7 分类
    Creative Commons
    • 热门文章
    • 热评文章
    • 随机文章
    • 在 Debian 服务器上部署 FileBrowser 并集成到现有博客路径
    • 高等数学重要定义整理
    • 高等数学重要定理总结
    • C语言原子量的使用
    • 库、链接与执行
    • 欢迎使用 Typecho
    • 对底层IO的深度总结
    • 数据结构——树
    • 库、链接与执行
    • shell作业控制的两个问题:组长叛变与SIGHUP信号
    • C语言原子量的使用
    • 高等数学重要定理总结
    • DNS(IP)与服务名(端口)解析
    • 高等数学刷题心得
    • UNIX 98伪终端核心系统调用及函数封装

    浏览量 : 5447

    © 2025 It's Geek KingYoungy. Power By Typecho . Theme by Shiyi

    浙ICP备2025160639号  |  浙公网安备33020502001222号

    This is just a placeholder img.