c++中socketpair函數(shù)示例詳解
socketpair() 是 Unix/Linux 系統(tǒng)中用于創(chuàng)建一對(duì)相互連接的匿名套接字的系統(tǒng)調(diào)用,專為 進(jìn)程間通信 (IPC) 設(shè)計(jì)。這對(duì)套接字在創(chuàng)建后即處于連接狀態(tài),無需綁定地址或手動(dòng)連接,特別適用于父子進(jìn)程或線程間通信。
函數(shù)原型
#include <sys/types.h> #include <sys/socket.h> int socketpair(int domain, int type, int protocol, int sv[2]);
| 參數(shù) | 說明 |
|---|---|
domain | 協(xié)議族:通常為 AF_UNIX(本地通信)或 AF_LOCAL(同義) |
type | 套接字類型:SOCK_STREAM(流式)或 SOCK_DGRAM(數(shù)據(jù)報(bào)) |
protocol | 協(xié)議:通常為 0(自動(dòng)選擇) |
sv[2] | 用于存儲(chǔ)兩個(gè)套接字描述符的數(shù)組(輸出參數(shù)) |
| 返回值 | 成功返回 0,失敗返回 -1 并設(shè)置 errno |
核心特性
- 匿名連接
- 套接字對(duì)在創(chuàng)建時(shí)已自動(dòng)連接,無需調(diào)用
bind(),listen(),accept(),connect()。
- 套接字對(duì)在創(chuàng)建時(shí)已自動(dòng)連接,無需調(diào)用
- 雙向通信
- 兩個(gè)套接字均可讀寫(全雙工)。
- 高效 IPC
- 數(shù)據(jù)在內(nèi)核中直接傳遞,無需經(jīng)過網(wǎng)絡(luò)協(xié)議棧。
- 無文件路徑
- 與命名 Unix 套接字不同,不會(huì)在文件系統(tǒng)中創(chuàng)建節(jié)點(diǎn)。
使用場(chǎng)景
- 父子進(jìn)程通信
- 父進(jìn)程創(chuàng)建套接字對(duì) →
fork()→ 父子進(jìn)程各關(guān)閉一端 → 通過剩余套接字通信。
- 父進(jìn)程創(chuàng)建套接字對(duì) →
- 線程間通信
- 線程可直接通過套接字描述符交換數(shù)據(jù)。
- 替代管道 (pipe)
- 提供雙向通信能力(管道是單向的)。
使用步驟
- 調(diào)用
socketpair()創(chuàng)建套接字對(duì) - 根據(jù)場(chǎng)景關(guān)閉不需要的描述符
- 通過
read()/write()或send()/recv()通信 - 通信完成后關(guān)閉所有描述符
示例代碼:父子進(jìn)程通信
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int sv[2]; // 套接字對(duì)
pid_t pid;
char buf[128];
// 1. 創(chuàng)建流式套接字對(duì)
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
perror("socketpair");
exit(1);
}
// 2. 創(chuàng)建子進(jìn)程
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { // 子進(jìn)程
close(sv[0]); // 關(guān)閉父進(jìn)程端
// 3. 向父進(jìn)程發(fā)送消息
const char *msg = "Hello from child";
write(sv[1], msg, strlen(msg) + 1);
// 4. 接收父進(jìn)程回復(fù)
read(sv[1], buf, sizeof(buf));
printf("Child received: %s\n", buf);
close(sv[1]); // 關(guān)閉子進(jìn)程端
exit(0);
}
else { // 父進(jìn)程
close(sv[1]); // 關(guān)閉子進(jìn)程端
// 3. 接收子進(jìn)程消息
read(sv[0], buf, sizeof(buf));
printf("Parent received: %s\n", buf);
// 4. 回復(fù)子進(jìn)程
const char *reply = "Hello from parent";
write(sv[0], reply, strlen(reply) + 1);
close(sv[0]); // 關(guān)閉父進(jìn)程端
wait(NULL); // 等待子進(jìn)程退出
}
return 0;
}關(guān)鍵參數(shù)詳解
1.domain協(xié)議族
AF_UNIX/AF_LOCAL
本地通信(進(jìn)程間通信),唯一推薦選項(xiàng)(其他如AF_INET通常不支持)。
2.type套接字類型
| 類型 | 特性 |
|---|---|
SOCK_STREAM | 可靠、雙向、面向連接的字節(jié)流(類似 TCP),無消息邊界 |
SOCK_DGRAM | 數(shù)據(jù)報(bào)服務(wù)(類似 UDP),保留消息邊界(在 AF_UNIX 中仍可靠) |
| 擴(kuò)展標(biāo)志 | |
SOCK_NONBLOCK | 非阻塞模式(Linux 特有,如 SOCK_STREAM | SOCK_NONBLOCK) |
SOCK_CLOEXEC | 執(zhí)行 exec 時(shí)關(guān)閉描述符(避免泄漏) |
3.protocol
- 固定為
0(系統(tǒng)自動(dòng)選擇協(xié)議)。
與管道的對(duì)比
| 特性 | socketpair() | pipe() |
|---|---|---|
| 通信方向 | 雙向(全雙工) | 單向(半雙工) |
| 數(shù)據(jù)流類型 | 流式/數(shù)據(jù)報(bào) | 字節(jié)流 |
| 描述符數(shù)量 | 2 個(gè)(均可讀寫) | 2 個(gè)(一個(gè)讀,一個(gè)寫) |
| 進(jìn)程關(guān)系 | 需繼承描述符(通常用于父子進(jìn)程) | 同左 |
| 控制能力 | 支持非阻塞、信號(hào)驅(qū)動(dòng)等高級(jí)選項(xiàng) | 功能有限 |
常見錯(cuò)誤處理
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
switch(errno) {
case EMFILE: // 進(jìn)程描述符耗盡
perror("Too many open files");
break;
case EAFNOSUPPORT: // 不支持的協(xié)議族
perror("Unsupported address family");
break;
case EPROTONOSUPPORT: // 不支持的協(xié)議
perror("Unsupported protocol");
break;
default:
perror("socketpair");
}
exit(EXIT_FAILURE);
}注意事項(xiàng)
- 描述符關(guān)閉
- 通信雙方需顯式關(guān)閉未使用的描述符(避免資源泄漏)。
- 協(xié)議族限制
- 可移植代碼應(yīng)僅使用
AF_UNIX(其他協(xié)議族如AF_INET可能不被支持)。
- 可移植代碼應(yīng)僅使用
- 阻塞與非阻塞
- 默認(rèn)阻塞模式,可通過
fcntl(fd, F_SETFL, O_NONBLOCK)或SOCK_NONBLOCK標(biāo)志設(shè)為非阻塞。
- 默認(rèn)阻塞模式,可通過
- 進(jìn)程關(guān)系
- 套接字對(duì)只能在有親緣關(guān)系的進(jìn)程間繼承(或通過
sendmsg()傳遞描述符)。
- 套接字對(duì)只能在有親緣關(guān)系的進(jìn)程間繼承(或通過
適用場(chǎng)景對(duì)比
| 場(chǎng)景 | 推薦方法 |
|---|---|
| 父子進(jìn)程雙向通信 | socketpair() |
| 無親緣關(guān)系進(jìn)程通信 | 命名 Unix 套接字 |
| 簡(jiǎn)單單向數(shù)據(jù)流(如日志) | pipe() |
| 高性能 IPC(Linux 特有) | eventfd()/signalfd() |
socketpair() 是進(jìn)程間雙向通信的輕量級(jí)解決方案,結(jié)合了管道的易用性和套接字的靈活性,尤其適合需要在親緣進(jìn)程間高效傳遞數(shù)據(jù)的場(chǎng)景。
到此這篇關(guān)于c++中socketpair函數(shù)示例詳解的文章就介紹到這了,更多相關(guān)c++ socketpair函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Dashboard Interface 應(yīng)用實(shí)現(xiàn)操作
Dashboard Server Remote Control Interface是一個(gè)關(guān)鍵的功能,它為用戶提供了通過TCP/IP協(xié)議遠(yuǎn)程控制機(jī)器人的能力,執(zhí)行包括開關(guān)機(jī)、加載程序、檢查機(jī)器人狀態(tài)以及設(shè)置機(jī)器人操作模式等多種操作,本文介紹Dashboard Interface 應(yīng)用操作,感興趣的朋友跟隨小編一起看看吧2024-08-08
正確理解C++的構(gòu)造函數(shù)和析構(gòu)函數(shù)
在C++的學(xué)習(xí)中,可以把類當(dāng)作一個(gè)模具,類實(shí)例化出來的對(duì)象就是根據(jù)這個(gè)模具所產(chǎn)生的實(shí)體,對(duì)象看作是自己創(chuàng)建的一個(gè)新的數(shù)據(jù)類型。本文主要介紹了類對(duì)象通過拷貝函數(shù)進(jìn)行初始化,分析類對(duì)象的內(nèi)存模型,以及通過this指針實(shí)現(xiàn)更復(fù)雜的功能。最后介紹了析構(gòu)函數(shù)的基礎(chǔ)知識(shí)2021-06-06
ubuntu系統(tǒng)vscodeC++編譯環(huán)境配置與使用方式
這篇文章主要介紹了ubuntu系統(tǒng)vscodeC++編譯環(huán)境配置與使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
OpenCV4.1.0+VisualStudio2019開發(fā)環(huán)境搭建(超級(jí)簡(jiǎn)單)
這篇文章主要介紹了OpenCV4.1.0+VisualStudio2019開發(fā)環(huán)境搭建(超級(jí)簡(jiǎn)單),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

