理论

管道内部传输的是字节流,TCP socket传输的也是字节流,区别在于:

  • 应用层程序能够往一个TCP连接中写入多少字节的数据,取决于对方的接收通告窗口的大小和本端的拥塞窗口的大小。
  • 管道本身拥有一个容量限制,它规定应用程序不将数据从管道读走的话,该管道最多能够写入多少字节的数据。从Linux2.6.11内核起,管道容量的大小默认是65536字节。我们可以用fcntl函数来修改管道容量

socket的基础API中有一个socketpair函数。它能够方便的创建双向管道:

#include <sys/types.h>
#include <sys/socket.h>/*
* socketpair()函数用于创建一对无名的、相互连接的套接子。
* 参数: domain必须是Unix本地域协议族AF_UNIX(因为仅能在本地使用这个双向管道)    sv[0]可读可写; sv[1] 可读可写
* 返回值:如果函数成功,则返回0,创建好的套接字分别是sv[0]和sv[1];否则返回-1,错误码保存于errno中。
*/
int socketpair(int domain, int type, int protocol, int sv[2]);

1、参数type、protocol和socket的type、protocol一样

  • socketpair()系统调用只能用在 UNIX domain 中,即 domain 参数必须被指定为AF_UNIX。
  • socket 的 type 可以被指定为 SOCK_DGRAM 或 SOCK_STREAM。
    • 将 type 指定为 SOCK_STREAM 相当于创建一个双向管道(也被称为流管道)。每个 socket都可以用来读取和写入,并且这两个 socket 之间每个方向上的数据信道是分开的。
    • 一般来讲,socket 对的使用方式与管道的使用方式类似。在调用完 socketpair()之后,进程会使用 fork()创建一个子进程。子进程会继承父进程的文件描述符的副本,包括引用 socket 对的描述符。因此父进程和子进程就可以使用这一对 socket 来进行 IPC 了
    • 使用 socketpair()创建一对 socket 与手工创建一对相互连接的 socket 这两种做法之间的一个差别在于前一对 socket 不会被绑定到任意地址上。这样就能够避免一类安全问题了,因为这一对 socket 对其他进程是不可见的
  • protocol 参数必须为 0。
  • sockfd数组返回了引用这两个相互连接的 socket 的文件描述符

2、基本用法

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

实践

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;
}

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

#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;
}

3、sendmsg读写socketpair

详情请参见Linux C/C++编程:数据读写

Unix/Linux编程:socketpair相关推荐

  1. 学习Unix/Linux编程要学些什么

    最近利用空余时间看了一下<Unix/Linux编程实践教程>,原书名为:Understanding Unix/Linux Programming: A Guide to Theory an ...

  2. 《Unix/linux编程实践教程》------重定向程序的I/O

    <Unix/linux编程实践教程>书中举例命令more的用法: $more filename $command | more $more < filename 用法1直接显示fil ...

  3. Unix/Linux编程:进程间通信(IPC)总结

    IPC工具分类 如上,Unix系统上IPC根据功能可以分为三类 通信:这些工具关注进程间的数据交换 同步:这些进程关注进程和线程操作之间的同步 信号:虽然信号的主要作用不为此,但是在特定场景下仍然可以 ...

  4. Unix/Linux编程实践教程–书评

    花了两个月的时间把这本书读完了,完成了一部分的课后习题. 总的来说,这是一本挺好的Unix\Linux编程的入门书(虽然书中的小错误一大堆),书的开始部分简要介绍了Unix系统编程,讲述了如何使用男人 ...

  5. stty详解-Unix/Linux编程实践教程第五章 学习stty

    读书笔记-第五章 连接控制 学习stty 先放上思维导图 为设备编程&设备就像文件 前面所学的知识都是基于文件的,而在unix/linux系统中,所有的设备(打印机,终端,话筒,摄像头等等)也 ...

  6. linux pipe函数 重定向,I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)...

    1.I/O重定向的概念与原因 及 标准输入.输出的标准错误的定义 所以的Unix I/O重定向都基于标准数据流的原理.三个数据了分别如下: 1)标准输入--需要处理的数据流 2)标准输出--结果数据流 ...

  7. Unix/Linux编程:Unix domain socket

    UNIX domain socket用于同一主机系统上的相互通信 UNIX domain socket 地址:struct sockaddr_un 在Unix domain中,socket地址以路径名 ...

  8. Unix/Linux编程:通用的IO模型

    概述 所有执行IO操作的系统调用都以文件描述符,一个非负整数(通常是小整数)来指代打开的文件 文件描述符用以表示所有类型的已打开文件,包括管道.FIFO.socket.终端.设备和普通文件 针对每个进 ...

  9. Unix/Linux编程:时间转换

    unix time stamp翻译为时间戳, 就是从1970年1月1日00:00::00以来的秒数. 程序可能会关注两种类型的时间 真实时间.度量这一时间的起点有二: 其一为某个标准点. 也叫做日历时 ...

最新文章

  1. 清晰易懂的Focal Loss原理解释
  2. 设置复杂密码为了防范谁? | 每日趣闻
  3. 公司用了 6 年的分布式锁,很是牛逼啊!
  4. 移动应用如何提升登录转化率
  5. Java 8 Lambda 表达式被编译成了什么?
  6. NoSQL技术入门简介
  7. MACOS上install_name_tool有时无法改变rpath
  8. mysql和oracle的字符串拼接_Oracle和Mysql中的字符串的拼接
  9. 酒店客房卫生打扫步骤及重点
  10. c语言程序设计在未来前景,转型背景下C程序设计课程的实施方案
  11. 我的c盘为多余的java.exejavaw.exe_java.exe,javac.exe,javaw.exe 是什么进程?
  12. QLabel(一) 内容换行
  13. C#控制台程序关闭快速编辑
  14. 封面型网页html,网站设计常用网页版式
  15. Sock学习1 (网络基本知识、Sock简介)
  16. win10无敌隐身术
  17. 番外7林芝·救赎之旅的最后一站——混合现实科幻《地与光》
  18. mxgraph 画布
  19. p2p与反p2p的激战--资料搜集
  20. mysql strtolower_自己写的mysql类_PHP教程 - strtolower

热门文章

  1. 【MC】我的世界零基础开云服务器教程
  2. 独立站营销广告的投放技巧和方法
  3. 给mysql用户授权命令_mysql添加用户并授权的命令(示例)
  4. Shell脚本实现将文本内容格式化为markdown表格文本
  5. 为什么国产手机的文件夹都是英文,不能换成中文?
  6. Win10系统怎么关闭自动设置时间功能?
  7. printf 格式化输出符号详细说明
  8. [AndroidStudio]安装、启动、模拟器相关、adb命令
  9. https 证书工具 Letsencrypt 简单教程
  10. Beego generate命令