socketpair函数用法

article/2025/9/22 11:29:32

Unix套接字好像是套接字和管道的混合,socketpair()可以创建一对无命名的、相互连接的Unix域套接字。

管道历史上,它们是半双工的(数据只能在一个方向上流动),但是现在也有全双工管道。管道只能在具有共同祖先的两个进程之间使用,通常一个管道由一个进程创建,在进程调用fork之后,这个管道就你能在父进程和子进程之间使用了。

socketpair()函数的声明:

#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int domain, int type, int protocol, int sockfd[2]);
socketpair()函数用于创建一对无名的、相互连接的套接字。 
如果函数成功,则返回0,创建好的套接字分别是sv[0]和sv[1];否则返回-1,错误码保存于errno中。

基本用法: 
1. 这对套接字可以用于全双工通信,每一个套接字既可以读也可以写。例如,可以往sockfd[0]中写,从sockfd[1]中读;或者从sockfd[1]中写,从sockfd[0]中读; 
2. 如果往一个套接字(如sockfd[0])中写入后,再从该套接字读时会阻塞,只能在另一个套接字中(sockfd[1])上读成功; 
3. 读、写操作可以位于同一个进程,也可以分别位于不同的进程,如父子进程。如果是父子进程时,一般会功能分离,一个进程用来读,一个用来写。因为文件描述符sockfd[0]和sockfd[1]是进程共享的,所以读的进程要关闭写描述符, 反之,写的进程关闭读描述符。 
举例: 
一、读写操作位于同一进程

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
 
const char* str = "SOCKET PAIR TEST.";
 
int main(int argc, char* argv[]){
    char buf[128] = {0};
    int socket_pair[2]; 
    pid_t pid; 
 
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { 
        printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE; 
    } 
 
    int size = write(socket_pair[0], str, strlen(str));
    //可以读取成功;
    read(socket_pair[1], buf, size);
    printf("Read result: %s\n",buf);
    return EXIT_SUCCESS;    

二、读写操作位于不同进程

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
 
const char* str = "SOCKET PAIR TEST.";
 
int main(int argc, char* argv[]){
    char buf[128] = {0};
    int socket_pair[2]; 
    pid_t pid; 
 
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { 
        printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE; 
    } 
 
    pid = fork();
    if(pid < 0) {
        printf("Error, fork failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE;
    } else if(pid > 0) {
        //关闭另外一个套接字
        close(socket_pair[1]);
        int size = write(socket_pair[0], str, strlen(str));
        printf("Write success, pid: %d\n", getpid());
 
    } else if(pid == 0) {
        //关闭另外一个套接字
        close(socket_pair[0]);
        read(socket_pair[1], buf, sizeof(buf));        
        printf("Read result: %s, pid: %d\n",buf, getpid());
    }
 
    for(;;) {
        sleep(1);
    }
 
    return EXIT_SUCCESS;    

sendmsg, recvmsg , send函数的使用
sendmsg, recvmsg , send三个函数的头文件:

#include <sys/types.h>  
#include <sys/socket.h>
sendmsg函数 
定义函数

          int sendmsg(int s, const strcut msghdr *msg, unsigned int flags);

函数说明:sendmsg()用来将数据由指定的socket传给对方主机. 
参数s:为已建立好连线的socket, 如果利用UDP协议则不需经过连线操作. 
参数msg:指向欲连线的数据结构内容, 参数flags 一般默认为0, 详细描述请参考send(). 
返回值:成功返回发送的字节数,出错返回-1

recvmsg函数 
定义函数

int recvmsg(int s, struct msghdr *msg, unsigned int flags);
函数说明:recvmsg()用来接收远程主机经指定的socket 传来的数据. 
参数s 为已建立好连线的socket, 如果利用UDP 协议则不需经过连线操作. 
参数msg 指向欲连线的数据结构内容, 
参数flags 一般设0, 详细描述请参考send(). 
返回值:成功则返回接收到的字符数, 失败则返回-1, 错误原因存于errno 中.

send函数 
定义函数:int send(int s, const void * msg, int len, unsigned int falgs); 
函数说明:send()用来将数据由指定的socket 传给对方主机. 
参数s 为已建立好连接的socket. 
参数msg 指向欲连线的数据内容. 
参数len 则为数据长度. 
参数flags 一般设0, 其他数值定义如下: 
MSG_OOB 传送的数据以out-of-band 送出. 
MSG_DONTROUTE 取消路由表查询 
MSG_DONTWAIT 设置为不可阻断运作 
MSG_NOSIGNAL 此动作不愿被SIGPIPE 信号中断. 
返回值:成功则返回实际传送出去的字符数, 失败返回-1. 错误原因存于errno.

结构msghdr定义如下:

struct msghdr
{
    void *msg_name; //发送或接收数据的地址
    socklen_t msg_namelen; //地址长度
    strcut iovec * msg_iov; //要发送或接受数据
    size_t msg_iovlen; //容器数据长度
    void * msg_control; //附属数据
    size_t msg_controllen; //附属数据长度
    int msg_flags; //接收消息的标志
};
返回值:成功则返回实际传送出去的字符数, 失败返回-1, 错误原因存于errno 
错误代码:

1、EBADF 参数s 非合法的socket 处理代码.
2、EFAULT 参数中有一指针指向无法存取的内存空间
3、ENOTSOCK 参数s 为一文件描述词, 非socket.
4、EINTR 被信号所中断.
5、EAGAIN 此操作会令进程阻断, 但参数s 的socket 为不可阻断.
6、ENOBUFS 系统的缓冲内存不足
7、ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确.
附属数据msg_control结构 
控制信息头部本身由下面的C结构定义:

struct cmsghdr {
    socklen_t cmsg_len;
    int       cmsg_level;
    int       cmsg_type;
/* u_char     cmsg_data[]; */
};
其成员描述如下:

成员             描述
cmsg_len        附属数据的字节计数,这包含结构头的尺寸。这个值是由CMSG_LEN()宏计算的。
cmsg_level      这个值表明了原始的协议级别(例如,SOL_SOCKET)。
cmsg_type       这个值表明了控制信息类型(例如,SCM_RIGHTS)。
cmsg_data       这个成员并不实际存在,用来指明实际的额外附属数据所在的位置。
用sendmsg来传递数据程序实例

/*sendmsg.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
 
int main(int argc,char *argv[])
{
    int ret;     /* 返回值 */
    int sock[2];    /* 套接字对 */
    struct msghdr msg;
    struct iovec iov[1];
    char send_buf[100] = "it is a test";
    struct msghdr msgr;
    struct iovec iovr[1];
    char recv_buf[100];
 
    /* 创建套接字对 */
    ret = socketpair(AF_LOCAL,SOCK_STREAM,0,sock);
    if(ret == -1){
        printf("socketpair err\n");
        return 1;   
    }
 
    /* sock[1]发送数据到本地主机  */
    bzero(&msg, sizeof(msg));
    msg.msg_name = NULL;        /* void*类型 NULL本地地址*/
    msg.msg_namelen = 0;
    iov[0].iov_base = send_buf;
    iov[0].iov_len = sizeof(send_buf);
    msg.msg_iov = iov;//要发送或接受数据设为iov
    msg.msg_iovlen = 1;//1个元素
 
    printf("开始发送数据:\n");
    printf("发送的数据为: %s\n", send_buf);
    ret = sendmsg(sock[1], &msg, 0 );
    if(ret == -1 ){
        printf("sendmsg err\n");
        return -1;
    }
    printf("发送成功!\n");
 
    /* 通过sock[0]接收发送过来的数据 */
    bzero(&msg, sizeof(msg));
    msgr.msg_name = NULL;   
    msgr.msg_namelen = 0;
    iovr[0].iov_base = &recv_buf;
    iovr[0].iov_len = sizeof(recv_buf);
    msgr.msg_iov = iovr;
    msgr.msg_iovlen = 1;
    ret = recvmsg(sock[0], &msgr, 0);
    if(ret == -1 ){
        printf("recvmsg err\n");
        return -1;
    }
    printf("接收成功!\n");
    printf("收到数据为: %s\n", recv_buf);
 
    /* 关闭sockets */
    close(sock[0]);
    close(sock[1]);
 
    return 0;
}
执行程序结果:

yu@ubuntu:~/Linux/217/pro_pool/socketpair$ gcc -o sendmsg sendmsg.c
yu@ubuntu:~/Linux/217/pro_pool/socketpair$ ./sendmsg
开始发送数据:
发送的数据为: it is a test
发送成功!
接收成功!
收到数据为: it is a test
程序分析:由套接字sock[1]发数据到本地主机,由套接字sock[0]接收发送过来的数据。
 


http://chatgpt.dhexx.cn/article/3c2DRCWq.shtml

相关文章

【socket】 unix域套接字(socketpair )通信|socketpair和pipe的区别|进程间通信-Unix domain socket

目录 unix域套接字&#xff08;socketpair )通信|socketpair和pipe的区别 socketpair机制 描述 原理 socketpair和pipe的区别 进程间通信-Unix domain socket unix域套接字&#xff08;socketpair )通信|socketpair和pipe的区别 2020-12-25 10:13:34 socketpair机制 描…

Android framework socketpair

简述 在Linux中&#xff0c;socketpair函数可以用于创建一对相互连接的、通信域为AF_UNIX的套接字&#xff0c;其中一个套接字可用于读取&#xff0c;另一个套接字可用于写入。可以使用这对套接字在同一进程内进行进程间通信&#xff08;IPC&#xff09;。 以下是使用socketp…

socketpair的理解

参考博客链接&#xff1a; https://blog.51cto.com/liulixiaoyao/533469 socketpair创建了一对无名的套接字描述符&#xff08;只能在AF_UNIX域中使用&#xff09;&#xff0c;描述符存储于一个二元数组eg. s[2] 这对套接字可以进行双工通信&#xff0c;每一个描述符既可以读也…

android socket双向,Android中socketpair双向通信详解

Android很多地方会涉及到进程间的通信&#xff0c;比如输入系统&#xff0c;那么进程间通信会涉及哪些内容呢&#xff1f; 1、进程&#xff1a;负责读取和分发事件 2、应用程序&#xff1a;负责处理输入事件 上面这两个进程会涉及哪些双向通信呢&#xff1a; 1.进程会发送输入事…

Linux下socketpair系统API调用使用说明

目录 1.socketpair函数说明 2.socketpair使用举例 在阅读nginx源码时&#xff0c;发现其调用socketpair来实现master和worker进程之间进行数据交互。其代码如下&#xff1a; 思考&#xff1a;master和worker进程是父子关系&#xff0c;有亲属关系的进程通过pipe/pipe2&#x…

socketpair函数介绍及使用

摘要 在linux下&#xff0c;使用socketpair函数能够创建一对套节字进行进程间通信&#xff08;IPC&#xff09;。 函数原形&#xff1a; #include <sys/types.h> #include <sys/socket.h>int socketpair(int domain, int type, int protocol, int sv[2]); 参数…

socketpair机制

描述 先看下传统的CS模型&#xff0c;如下: 总是一方发起请求&#xff0c;等待另一方回应。当一次传输完成之后&#xff0c;client端发起新的请求之后&#xff0c;server端才作出回应。 那如何才能做到双向通信&#xff1f; 一种解决办法就是client端即使client&#xff0c;又…

【socketpair函数介绍及使用】

socketpair函数介绍及使用 函数原型进程间通信线程间通信 Linux环境下使用socketpair函数创造一对未命名的、相互连接的UNIX域套接字。   管道历史上&#xff0c;它们是半双工的&#xff08;数据只能在一个方向上流动&#xff09;&#xff0c;但是现在也有全双工管道。管道只…

LAMP架构超详细搭建步骤

LAMP介绍&#xff1a; LinuxApacheMysql/MariaDBPerl/PHP/Python一组常用来搭建或者服务器的开源软件&#xff0c;本身都是各自独立的程序&#xff0c;但是因为常被放在一起使用&#xff0c;拥有了越来越高的兼容度&#xff0c;共同组成了一个强大的Web应用程序平台。 目前LA…

LAMP架构介绍

转载自&#xff1a; https://blog.csdn.net/aoli_shuai/article/details/78745984 https://blog.csdn.net/sj349781478/article/details/84224440 一、LAMP介绍&#xff1a; LAMP是 linux Apache MySQL PHP的简写&#xff0c;即把Apache MySQL PHP 安装在linux系统上&#xff…

Lamp架构部署phpmadmin项目

Lamp架构部署phpmadmin项目 文章目录 Lamp架构部署phpmadmin项目官网下载phpmadmin的包测试登陆 官网下载phpmadmin的包 [phpMyAdmin]: 将下载好的包拖入目录里&#xff0c;并解压 [rootlocalhost ~]# cd /usr/src/ [rootlocalhost src]# lsapr-1.6.5 apr-1.6.5.tar.gz a…

【笔记】lamp架构框图

一、lamp架构 (1)、lamp基础结构 (2)、分布式lamp架构 (3)、实际运用 二、OSI七层和TCP/IP五层关系 这部分具体可以参考网址 (1)、OSI七层 OSI&#xff08;Open System Interconnect&#xff09;&#xff0c;即开放式系统互联。 一般都叫OSI参考模型&#xff0c;是ISO&…

LAMP服务架构

LAMP服务架构 文章目录 LAMP服务架构1. LAMP简介2. LAMP工作原理3. 部署LAMP3.1 源码安装http服务3.2 源码安装mysql数据库3.3 源码安装php3.2 apache和php配置 1. LAMP简介 LAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写 L代表服务器操作系统使用…

LAMP架构部署论坛

搭建论坛&#xff0c;要求为8080端口 安装LAMP 架构所需的服务&#xff0c;部分及插件 yum -y install mariadb mariadb-server mariadb-libs php php-mysql php-gd php-fpm php-cli gd httpd 启动服务&#xff1a;systemctl start httpd mariadb 设置数据库密码&#xff1a…

快速搭建LAMP架构

快速搭建LAMP架构 1.安装apache2.部署mysql3.部署php结合apache4.验证5.部署一个论坛disuz 1.安装apache [rootlocalhost ~]# yum install httpd -y 已加载插件&#xff1a;fastestmirror, langpacks Loading mirror speeds from cached hostfile* base: mirrors.aliyun.com* …

LAMP架构简介与配置

文章目录 前言LAMP 简介与概述LAMP平台概述 构建LAMP平台顺序编译安装的优点各组件的主要作用 编译安装 Apache编译安装mysql安装PHP 前言 LAMP 简介与概述 LAMP平台概述 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整台系统和相关软件&#x…

搭建LAMP架构

搭建LAMP架构 一、LAMP架构概述 1、LAMP简介 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整台系统和相关软件&#xff0c;能够提供动态web站点服务及其应用开发环境。 LAMP是一个缩写词&#xff0c;具体包括Linux操作系统&#xff0c;Apache网…

LAMP架构简介与概述 及服务安装

目录 1、LAMP平台概述 &#xff08;1&#xff09;LAMP平台概述 &#xff08;2&#xff09;构建LAMP平台顺序 &#xff08;3&#xff09;编译安装的优点 &#xff08;4&#xff09;各组件的主要作用 2、Apache概述 &#xff08;1&#xff09; 安装Apache服务&#xff1a;…

什么是LAMP架构?

LAMP架构介绍 LAMP动态网站架构 LAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写。 1、LAMP分别代表什么&#xff1f; L代表服务器操作系统使用Linux A代表网站服务使用的是Apache软件基金会中的httpd软件 M代表网站后台使用的数据库是MySQL数…

【ubuntu】搭建lamp架构

文章目录 一、准备工作1、更新源2、更新软件3、防火墙UFW 二、安装apache21、安装apache包2、网页浏览查看 三、安装mysql1、安装mysql2、查看mysql3、设置mysql数据库的密码 四、安装PHP1、安装php包以及插件2、测试php包 五、安装wordpress1、获取wordpress的压缩包2、上传压…