c++中socketpair函数示例详解

 更新时间:2025年07月29日 10:37:54   作者:青草地溪水旁  
socketpair()创建已连接的匿名Unix套接字对,用于高效进程间通信,无需绑定或连接,支持双向流式/数据报通信,适用于父子进程和线程,相比管道,提供全双工能力,结合了易用性与灵活性,本文给大家介绍c++中socketpair函数示例,感兴趣的朋友一起看看吧

socketpair() 是 Unix/Linux 系统中用于创建一对相互连接的匿名套接字的系统调用,专为 进程间通信 (IPC) 设计。这对套接字在创建后即处于连接状态,无需绑定地址或手动连接,特别适用于父子进程或线程间通信。

函数原型

#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int domain, int type, int protocol, int sv[2]);
参数说明
domain协议族:通常为 AF_UNIX(本地通信)或 AF_LOCAL(同义)
type套接字类型:SOCK_STREAM(流式)或 SOCK_DGRAM(数据报)
protocol协议:通常为 0(自动选择)
sv[2]用于存储两个套接字描述符的数组(输出参数)
返回值成功返回 0,失败返回 -1 并设置 errno

核心特性

  1. 匿名连接
    • 套接字对在创建时已自动连接,无需调用 bind(), listen(), accept(), connect()
  2. 双向通信
    • 两个套接字均可读写(全双工)。
  3. 高效 IPC
    • 数据在内核中直接传递,无需经过网络协议栈。
  4. 无文件路径
    • 与命名 Unix 套接字不同,不会在文件系统中创建节点。

使用场景

  1. 父子进程通信
    • 父进程创建套接字对 → fork() → 父子进程各关闭一端 → 通过剩余套接字通信。
  2. 线程间通信
    • 线程可直接通过套接字描述符交换数据。
  3. 替代管道 (pipe)
    • 提供双向通信能力(管道是单向的)。

使用步骤

  1. 调用 socketpair() 创建套接字对
  2. 根据场景关闭不需要的描述符
  3. 通过 read()/write()send()/recv() 通信
  4. 通信完成后关闭所有描述符

示例代码:父子进程通信

#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    int sv[2];  // 套接字对
    pid_t pid;
    char buf[128];
    // 1. 创建流式套接字对
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
        perror("socketpair");
        exit(1);
    }
    // 2. 创建子进程
    pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(1);
    }
    if (pid == 0) { // 子进程
        close(sv[0]);  // 关闭父进程端
        // 3. 向父进程发送消息
        const char *msg = "Hello from child";
        write(sv[1], msg, strlen(msg) + 1);
        // 4. 接收父进程回复
        read(sv[1], buf, sizeof(buf));
        printf("Child received: %s\n", buf);
        close(sv[1]);  // 关闭子进程端
        exit(0);
    } 
    else { // 父进程
        close(sv[1]);  // 关闭子进程端
        // 3. 接收子进程消息
        read(sv[0], buf, sizeof(buf));
        printf("Parent received: %s\n", buf);
        // 4. 回复子进程
        const char *reply = "Hello from parent";
        write(sv[0], reply, strlen(reply) + 1);
        close(sv[0]);  // 关闭父进程端
        wait(NULL);    // 等待子进程退出
    }
    return 0;
}

关键参数详解

1.domain协议族

  • AF_UNIX / AF_LOCAL
    本地通信(进程间通信),唯一推荐选项(其他如 AF_INET 通常不支持)。

2.type套接字类型

类型特性
SOCK_STREAM可靠、双向、面向连接的字节流(类似 TCP),无消息边界
SOCK_DGRAM数据报服务(类似 UDP),保留消息边界(在 AF_UNIX 中仍可靠)
扩展标志
SOCK_NONBLOCK非阻塞模式(Linux 特有,如 SOCK_STREAM | SOCK_NONBLOCK
SOCK_CLOEXEC执行 exec 时关闭描述符(避免泄漏)

3.protocol

  • 固定为 0(系统自动选择协议)。

与管道的对比

特性socketpair()pipe()
通信方向双向(全双工)单向(半双工)
数据流类型流式/数据报字节流
描述符数量2 个(均可读写)2 个(一个读,一个写)
进程关系需继承描述符(通常用于父子进程)同左
控制能力支持非阻塞、信号驱动等高级选项功能有限

常见错误处理

if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
    switch(errno) {
        case EMFILE:  // 进程描述符耗尽
            perror("Too many open files");
            break;
        case EAFNOSUPPORT: // 不支持的协议族
            perror("Unsupported address family");
            break;
        case EPROTONOSUPPORT: // 不支持的协议
            perror("Unsupported protocol");
            break;
        default:
            perror("socketpair");
    }
    exit(EXIT_FAILURE);
}

注意事项

  1. 描述符关闭
    • 通信双方需显式关闭未使用的描述符(避免资源泄漏)。
  2. 协议族限制
    • 可移植代码应仅使用 AF_UNIX(其他协议族如 AF_INET 可能不被支持)。
  3. 阻塞与非阻塞
    • 默认阻塞模式,可通过 fcntl(fd, F_SETFL, O_NONBLOCK)SOCK_NONBLOCK 标志设为非阻塞。
  4. 进程关系
    • 套接字对只能在有亲缘关系的进程间继承(或通过 sendmsg() 传递描述符)。

适用场景对比

场景推荐方法
父子进程双向通信socketpair()
无亲缘关系进程通信命名 Unix 套接字
简单单向数据流(如日志)pipe()
高性能 IPC(Linux 特有)eventfd()/signalfd()

socketpair() 是进程间双向通信的轻量级解决方案,结合了管道的易用性和套接字的灵活性,尤其适合需要在亲缘进程间高效传递数据的场景。

到此这篇关于c++中socketpair函数示例详解的文章就介绍到这了,更多相关c++ socketpair函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Dashboard Interface 应用实现操作

    Dashboard Interface 应用实现操作

    Dashboard Server Remote Control Interface是一个关键的功能,它为用户提供了通过TCP/IP协议远程控制机器人的能力,执行包括开关机、加载程序、检查机器人状态以及设置机器人操作模式等多种操作,本文介绍Dashboard Interface 应用操作,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • 浅谈分词器Tokenizer

    浅谈分词器Tokenizer

    分词器的工作就是分解文本流成词(tokens).在这个文本中,每一个token都是这些字符的一个子序列。一个分析器(analyzer)必须知道它所配置的字段,但是tokenizer不需要,分词器(tokenizer)从一个字符流(reader)读取数据,生成一个Token对象(TokenStream)的序列
    2021-06-06
  • 正确理解C++的构造函数和析构函数

    正确理解C++的构造函数和析构函数

    在C++的学习中,可以把类当作一个模具,类实例化出来的对象就是根据这个模具所产生的实体,对象看作是自己创建的一个新的数据类型。本文主要介绍了类对象通过拷贝函数进行初始化,分析类对象的内存模型,以及通过this指针实现更复杂的功能。最后介绍了析构函数的基础知识
    2021-06-06
  • c++读取excel的代码详解

    c++读取excel的代码详解

    在本篇文章里小编给大家分享的是一篇关于c++读取excel的代码详解内容,需要的朋友们可以学习参考下。
    2020-02-02
  • ubuntu系统vscodeC++编译环境配置与使用方式

    ubuntu系统vscodeC++编译环境配置与使用方式

    这篇文章主要介绍了ubuntu系统vscodeC++编译环境配置与使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • OpenCV4.1.0+VisualStudio2019开发环境搭建(超级简单)

    OpenCV4.1.0+VisualStudio2019开发环境搭建(超级简单)

    这篇文章主要介绍了OpenCV4.1.0+VisualStudio2019开发环境搭建(超级简单),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • C++四种cast使用详细介绍

    C++四种cast使用详细介绍

    本文主要介绍了C++四种cast使用详细介绍,今天我们要来讲的是显式类型转换,C++提供了四种显式类型转换,分别是:static_cast、dynamic_cast、const_cast、reinterpret_cast,感兴趣的可以了解一下
    2022-07-07
  • C语言编程中函数的基本学习教程

    C语言编程中函数的基本学习教程

    这篇文章主要介绍了C语言编程中函数的基本学习教程,其中着重讲到了传值调用与参数,需要的朋友可以参考下
    2015-12-12
  • C语言实现三子棋源代码

    C语言实现三子棋源代码

    这篇文章主要为大家详细介绍了C语言实现三子棋源代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • C++万能库头文件在vs中的安装步骤(图文)

    C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02

最新评论