Unix/Linux编程:socketpair
理论
管道内部传输的是字节流,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、基本用法
- 这对套接字可以用于全双工通信,每一个套接字既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读;或者从sv[1]中写,从sv[0]中读;
- 如果往一个套接字(如sv[0])中写入后,再从该套接字读时会阻塞,只能在另一个套接字中(sv[1])上读成功;
- 读、写操作可以位于同一个进程,也可以分别位于不同的进程,如父子进程。如果是父子进程时,一般会功能分离,一个进程用来读,一个用来写。因为文件描述副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相关推荐
- 学习Unix/Linux编程要学些什么
最近利用空余时间看了一下<Unix/Linux编程实践教程>,原书名为:Understanding Unix/Linux Programming: A Guide to Theory an ...
- 《Unix/linux编程实践教程》------重定向程序的I/O
<Unix/linux编程实践教程>书中举例命令more的用法: $more filename $command | more $more < filename 用法1直接显示fil ...
- Unix/Linux编程:进程间通信(IPC)总结
IPC工具分类 如上,Unix系统上IPC根据功能可以分为三类 通信:这些工具关注进程间的数据交换 同步:这些进程关注进程和线程操作之间的同步 信号:虽然信号的主要作用不为此,但是在特定场景下仍然可以 ...
- Unix/Linux编程实践教程–书评
花了两个月的时间把这本书读完了,完成了一部分的课后习题. 总的来说,这是一本挺好的Unix\Linux编程的入门书(虽然书中的小错误一大堆),书的开始部分简要介绍了Unix系统编程,讲述了如何使用男人 ...
- stty详解-Unix/Linux编程实践教程第五章 学习stty
读书笔记-第五章 连接控制 学习stty 先放上思维导图 为设备编程&设备就像文件 前面所学的知识都是基于文件的,而在unix/linux系统中,所有的设备(打印机,终端,话筒,摄像头等等)也 ...
- linux pipe函数 重定向,I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)...
1.I/O重定向的概念与原因 及 标准输入.输出的标准错误的定义 所以的Unix I/O重定向都基于标准数据流的原理.三个数据了分别如下: 1)标准输入--需要处理的数据流 2)标准输出--结果数据流 ...
- Unix/Linux编程:Unix domain socket
UNIX domain socket用于同一主机系统上的相互通信 UNIX domain socket 地址:struct sockaddr_un 在Unix domain中,socket地址以路径名 ...
- Unix/Linux编程:通用的IO模型
概述 所有执行IO操作的系统调用都以文件描述符,一个非负整数(通常是小整数)来指代打开的文件 文件描述符用以表示所有类型的已打开文件,包括管道.FIFO.socket.终端.设备和普通文件 针对每个进 ...
- Unix/Linux编程:时间转换
unix time stamp翻译为时间戳, 就是从1970年1月1日00:00::00以来的秒数. 程序可能会关注两种类型的时间 真实时间.度量这一时间的起点有二: 其一为某个标准点. 也叫做日历时 ...
最新文章
- 清晰易懂的Focal Loss原理解释
- 设置复杂密码为了防范谁? | 每日趣闻
- 公司用了 6 年的分布式锁,很是牛逼啊!
- 移动应用如何提升登录转化率
- Java 8 Lambda 表达式被编译成了什么?
- NoSQL技术入门简介
- MACOS上install_name_tool有时无法改变rpath
- mysql和oracle的字符串拼接_Oracle和Mysql中的字符串的拼接
- 酒店客房卫生打扫步骤及重点
- c语言程序设计在未来前景,转型背景下C程序设计课程的实施方案
- 我的c盘为多余的java.exejavaw.exe_java.exe,javac.exe,javaw.exe 是什么进程?
- QLabel(一) 内容换行
- C#控制台程序关闭快速编辑
- 封面型网页html,网站设计常用网页版式
- Sock学习1 (网络基本知识、Sock简介)
- win10无敌隐身术
- 番外7林芝·救赎之旅的最后一站——混合现实科幻《地与光》
- mxgraph 画布
- p2p与反p2p的激战--资料搜集
- mysql strtolower_自己写的mysql类_PHP教程 - strtolower