我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言 socketpair用法案例讲解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C语言 socketpair用法案例讲解

socketpair()函数的声明:


#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int d, int type, int protocol, int sv[2]);

socketpair()函数用于创建一对无名的、相互连接的套接子。 
如果函数成功,则返回0,创建好的套接字分别是sv[0]和sv[1];否则返回-1,错误码保存于errno中。

基本用法: 

  1. 这对套接字可以用于全双工通信,每一个套接字既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读;或者从sv[1]中写,从sv[0]中读; 
  2. 如果往一个套接字(如sv[0])中写入后,再从该套接字读时会阻塞,只能在另一个套接字中(sv[1])上读成功; 
  3. 读、写操作可以位于同一个进程,也可以分别位于不同的进程,如父子进程。如果是父子进程时,一般会功能分离,一个进程用来读,一个用来写。因为文件描述副sv[0]和sv[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;

};

其成员描述如下:


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

用sendmsg来传递数据程序实例



#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;   
    }
 
    
    bzero(&msg, sizeof(msg));
    msg.msg_name = 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");
 
    
    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);
 
    
    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]接收发送过来的数据。

到此这篇关于C语言 socketpair用法案例讲解的文章就介绍到这了,更多相关C语言 socketpair用法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C语言 socketpair用法案例讲解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C语言socketpair的使用方法是什么

在C语言中,可以使用socketpair函数来创建一对相互连接的套接字。这对套接字可以用于在同一进程内进行通信。下面是socketpair函数的使用方法:#include int socketpair(int
C语言socketpair的使用方法是什么
2024-03-06

Python中import语句用法案例讲解

在实际应用中,有时程序所要实现功能比较复杂,代码量也很大,若把所有的代码都存储在一个文件中,则不利于代码的复用和维护,这篇文章主要介绍了Python中import语句用法详解,需要的朋友可以参考下
2022-12-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录