c++中socketpair函數(shù)示例詳解
socketpair() 是 Unix/Linux 系統(tǒng)中用于創(chuàng)建一對(duì)相互連接的匿名套接字的系統(tǒng)調(diào)用,專(zhuān)為 進(jìn)程間通信 (IPC) 設(shè)計(jì)。這對(duì)套接字在創(chuàng)建后即處于連接狀態(tài),無(wú)需綁定地址或手動(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ù) | 說(shuō)明 |
|---|---|
domain | 協(xié)議族:通常為 AF_UNIX(本地通信)或 AF_LOCAL(同義) |
type | 套接字類(lèi)型: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)連接,無(wú)需調(diào)用
bind(),listen(),accept(),connect()。
- 套接字對(duì)在創(chuàng)建時(shí)已自動(dòng)連接,無(wú)需調(diào)用
- 雙向通信
- 兩個(gè)套接字均可讀寫(xiě)(全雙工)。
- 高效 IPC
- 數(shù)據(jù)在內(nèi)核中直接傳遞,無(wú)需經(jīng)過(guò)網(wǎng)絡(luò)協(xié)議棧。
- 無(wú)文件路徑
- 與命名 Unix 套接字不同,不會(huì)在文件系統(tǒng)中創(chuàng)建節(jié)點(diǎn)。
使用場(chǎng)景
- 父子進(jìn)程通信
- 父進(jìn)程創(chuàng)建套接字對(duì) →
fork()→ 父子進(jìn)程各關(guān)閉一端 → 通過(guò)剩余套接字通信。
- 父進(jìn)程創(chuàng)建套接字對(duì) →
- 線程間通信
- 線程可直接通過(guò)套接字描述符交換數(shù)據(jù)。
- 替代管道 (pipe)
- 提供雙向通信能力(管道是單向的)。
使用步驟
- 調(diào)用
socketpair()創(chuàng)建套接字對(duì) - 根據(jù)場(chǎng)景關(guān)閉不需要的描述符
- 通過(guò)
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套接字類(lèi)型
| 類(lèi)型 | 特性 |
|---|---|
SOCK_STREAM | 可靠、雙向、面向連接的字節(jié)流(類(lèi)似 TCP),無(wú)消息邊界 |
SOCK_DGRAM | 數(shù)據(jù)報(bào)服務(wù)(類(lèi)似 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ù)流類(lèi)型 | 流式/數(shù)據(jù)報(bào) | 字節(jié)流 |
| 描述符數(shù)量 | 2 個(gè)(均可讀寫(xiě)) | 2 個(gè)(一個(gè)讀,一個(gè)寫(xiě)) |
| 進(jìn)程關(guān)系 | 需繼承描述符(通常用于父子進(jìn)程) | 同左 |
| 控制能力 | 支持非阻塞、信號(hào)驅(qū)動(dòng)等高級(jí)選項(xiàng) | 功能有限 |
常見(jiàn)錯(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)阻塞模式,可通過(guò)
fcntl(fd, F_SETFL, O_NONBLOCK)或SOCK_NONBLOCK標(biāo)志設(shè)為非阻塞。
- 默認(rèn)阻塞模式,可通過(guò)
- 進(jìn)程關(guān)系
- 套接字對(duì)只能在有親緣關(guān)系的進(jìn)程間繼承(或通過(guò)
sendmsg()傳遞描述符)。
- 套接字對(duì)只能在有親緣關(guān)系的進(jìn)程間繼承(或通過(guò)
適用場(chǎng)景對(duì)比
| 場(chǎng)景 | 推薦方法 |
|---|---|
| 父子進(jìn)程雙向通信 | socketpair() |
| 無(wú)親緣關(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)文章
C語(yǔ)言程序中結(jié)構(gòu)體的內(nèi)存對(duì)齊詳解
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言程序中結(jié)構(gòu)體的內(nèi)存對(duì)齊的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下2022-11-11
C語(yǔ)言基于graphics.h實(shí)現(xiàn)圣誕樹(shù)
這篇文章主要介紹了圣誕樹(shù)代碼,c語(yǔ)言編程,基于graphics.h實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
matlab實(shí)現(xiàn)繪制玫瑰花球的示例代碼
這篇文章主要介紹了如何利用matlab實(shí)現(xiàn)繪制玫瑰花球,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定的幫助,需要的可以參考一下2023-08-08
windows下安裝QT及visual studio 2017搭建開(kāi)發(fā)環(huán)境
這篇文章主要介紹了windows下安裝QT及visual studio 2017搭建開(kāi)發(fā)環(huán)境,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
Qt利用QSortFilterProxyModel代理實(shí)現(xiàn)自定義排序與聯(lián)合過(guò)濾
QsortFilterProxyModel類(lèi)用來(lái)為model和view之間提供強(qiáng)大的排序和過(guò)濾支持。這篇文章將利用QSortFilterProxyModel代理實(shí)現(xiàn)自定義排序與聯(lián)合過(guò)濾,需要的可以參考一下2022-11-11
C語(yǔ)言動(dòng)態(tài)內(nèi)存管理的實(shí)現(xiàn)
本文主要介紹了C語(yǔ)言動(dòng)態(tài)內(nèi)存管理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Visual?Studio?2022?安裝低版本?.Net?Framework的圖文教程
這篇文章主要介紹了Visual?Studio?2022?如何安裝低版本的?.Net?Framework,首先打開(kāi)?Visual?Studio?Installer?可以看到vs2022?只支持安裝4.6及以上的版本,那么該如何安裝4.6以下的版本,下面將詳細(xì)介紹,需要的朋友可以參考下2022-09-09

