Unix domain socket 简介

news/发布时间2024/8/25 6:46:04

原文: https://www.cnblogs.com/sparkdev/p/8359028.html

 

Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信。socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
UNIX domain socket 是全双工的,API 接口语义丰富,相比其它 IPC 机制有明显的优越性,目前已成为使用最广泛的 IPC 机制,比如 X Window 服务器和 GUI 程序之间就是通过 UNIX domain socket 通讯的。
Unix domain socket 是 POSIX 标准中的一个组件,所以不要被名字迷惑,linux 系统也是支持它的。

下面通过一个简单的 demo 来理解相关概念。程序分为服务器端和客户端两部分,它们之间通过 unix domain socket 进行通信。

服务器端程序

下面是一个非常简单的服务器端程序,它从客户端读字符,然后将每个字符转换为大写并回送给客户端:

复制代码
#include <stdlib.h>  
#include <stdio.h>  
#include <stddef.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <errno.h>  
#include <string.h>  
#include <unistd.h>  
#include <ctype.h>   #define MAXLINE 80  char *socket_path = "server.socket";  int main(void)  
{  struct sockaddr_un serun, cliun;  socklen_t cliun_len;  int listenfd, connfd, size;  char buf[MAXLINE];  int i, n;  if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {  perror("socket error");  exit(1);  }  memset(&serun, 0, sizeof(serun));  serun.sun_family = AF_UNIX;  strcpy(serun.sun_path, socket_path);  size = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path);  unlink(socket_path);  if (bind(listenfd, (struct sockaddr *)&serun, size) < 0) {  perror("bind error");  exit(1);  }  printf("UNIX domain socket bound\n");  if (listen(listenfd, 20) < 0) {  perror("listen error");  exit(1);          }  printf("Accepting connections ...\n");  while(1) {  cliun_len = sizeof(cliun);         if ((connfd = accept(listenfd, (struct sockaddr *)&cliun, &cliun_len)) < 0){  perror("accept error");  continue;  }  while(1) {  n = read(connfd, buf, sizeof(buf));  if (n < 0) {  perror("read error");  break;  } else if(n == 0) {  printf("EOF\n");  break;  }  printf("received: %s", buf);  for(i = 0; i < n; i++) {  buf[i] = toupper(buf[i]);  }  write(connfd, buf, n);  }  close(connfd);  }  close(listenfd);  return 0;  
} 
复制代码

简单介绍一下这段代码:

int socket(int family, int type, int protocol);

使用 UNIX domain socket 的过程和网络 socket 十分相似,也要先调用 socket() 创建一个 socket 文件描述符.
family 指定为 AF_UNIX,使用 AF_UNIX 会在系统上创建一个 socket 文件,不同进程通过读写这个文件来实现通信。
type 可以选择 SOCK_DGRAM 或 SOCK_STREAM。SOCK_STREAM 意味着会提供按顺序的、可靠、双向、面向连接的比特流。SOCK_DGRAM 意味着会提供定长的、不可靠、无连接的通信。
protocol 参数指定为 0 即可。
UNIX domain socket 与网络 socket 编程最明显的不同在于地址格式不同,用结构体 sockaddr_un 表示,网络编程的 socket 地址是 IP 地址加端口号,而 UNIX domain socket 的地址是一个 socket 类型的文件在文件系统中的路径,这个 socket 文件由 bind() 调用创建,如果调用 bind() 时该文件已存在,则 bind() 错误返回。因此,一般在调用 bind() 前会检查 socket 文件是否存在,如果存在就删除掉。
网络 socket 编程类似,在 bind 之后要 listen,表示通过 bind 的地址(也就是 socket 文件)提供服务。
接下来必须用 accept() 函数初始化连接。accept() 为每个连接创立新的套接字并从监听队列中移除这个连接。

客户端程序

下面是客户端程序,它接受用户的输入,并把字符串发送给服务器,然后接收服务器返回的字符串并打印:

复制代码
#include <stdlib.h>  
#include <stdio.h>  
#include <stddef.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <errno.h>  
#include <string.h>  
#include <unistd.h>  #define MAXLINE 80  char *client_path = "client.socket";  
char *server_path = "server.socket";  int main() {  struct  sockaddr_un cliun, serun;  int len;  char buf[100];  int sockfd, n;  if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){  perror("client socket error");  exit(1);  }  // 一般显式调用bind函数,以便服务器区分不同客户端  memset(&cliun, 0, sizeof(cliun));  cliun.sun_family = AF_UNIX;  strcpy(cliun.sun_path, client_path);  len = offsetof(struct sockaddr_un, sun_path) + strlen(cliun.sun_path);  unlink(cliun.sun_path);  if (bind(sockfd, (struct sockaddr *)&cliun, len) < 0) {  perror("bind error");  exit(1);  }  memset(&serun, 0, sizeof(serun));  serun.sun_family = AF_UNIX;  strcpy(serun.sun_path, server_path);  len = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path);  if (connect(sockfd, (struct sockaddr *)&serun, len) < 0){  perror("connect error");  exit(1);  }  while(fgets(buf, MAXLINE, stdin) != NULL) {    write(sockfd, buf, strlen(buf));    n = read(sockfd, buf, MAXLINE);    if ( n < 0 ) {    printf("the other side has been closed.\n");    }else {    write(STDOUT_FILENO, buf, n);    }    }   close(sockfd);  return 0;  
}  
复制代码

与网络 socket 编程不同的是,UNIX domain socket 客户端一般要显式调用 bind 函数,而不依赖系统自动分配的地址。客户端 bind 一个自己指定的 socket 文件名的好处是,该文件名可以包含客户端的 pid 等信息以便服务器区分不同的客户端。

运行上面的程序

分别把服务器端程序和客户端程序保存为 server.c 和 client.c 文件,并编译:

$ gcc server.c -o server
$ gcc client.c -o client

先启动服务器端程序,然后启动客户端程序输入字符串并回车:

还不错,客户端得到了服务器端返回的大写字符串。接下来看看当前目录下的文件:

哈哈,多了两个 socket 文件。

总结

Unix domain socket 主要用于同一主机上的进程间通信。与主机间的进程通信不同,它不是通过 "IP地址 + TCP或UDP端口号" 的方式进程通信,而是使用 socket 类型的文件来完成通信,因此在稳定性、可靠性以及效率方面的表现都很不错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.liansuoyi.cn/news/68445155.html

如若内容造成侵权/违法违规/事实不符,请联系连锁易网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

使用Github Action实现构建、发布到 nuget.org

使用Github Action实现构建、发布到 nuget.org GitHub Actions是GitHub提供的持续集成和持续部署(CI/CD)工具,它能够自动化构建、测试和部署你的项目。在这篇教程中,我们将探讨如何使用GitHub Actions来构建一个.NET项目,并将它发布到 NuGet.org。 配置 NuGet API 密钥首先…

pmp团队建设的塔克曼阶梯理论的五个阶段

塔克曼阶梯理论是由Bruce Tuckman在1965年提出的,用于描述团队如何成长、面对挑战、解决问题、发展团队工作方法,并优化性能的过程。这个理论后来在1977年被Tuckman和Mary Ann Jensen进一步完善,增加了第五个阶段。以下是Tuckman的五个阶段及其特征:形成 (Forming):成员们正…

《信息安全系统设计与实现》第六周学习笔记

一、课程内容第十一章学习 EXT2文件数据结构 1、通过mkfs创建虚拟磁盘 mke2fs [-b blksize -N ninodes] device nblocks 虚拟磁盘布局:2、操作系统内核中的文件系统函数 3、系统调用 4、I/O库函数 5、用户命令 6、sh脚本 低级别的文件操作中的常用函数: 打开和关闭文件: ope…

振弦采集仪应用水坝安全监测的方案

振弦采集仪应用水坝安全监测的方案 随着工业化和城市化的快速发展,水资源的开发和利用越来越广泛。由于水坝在水利工程中起着至关重要的作用,因此对水坝进行安全监测变得越来越必要。为了实现对水坝的安全监测,振弦采集仪可以作为一种有效的工具进行应用。本文将探讨振弦采集…

离开了浪浪山,简直不要太爽

今年年初的时候,《中国奇谭》火了,与其说是《中国奇谭》火了,还不如说是这个动漫和普通打工人太有共鸣了,动漫里面的小猪妖是很多普通打工人的写照,毕业进入了父母亲戚以为很不错的工作,领着一份不多不少的工资,每天要处理各种工作上的事情,事情比较多的时候,还需要经…

Julia基础知识

在本章中,我们将学习并行计算所需的Julia基本部分:变量 函数 数组在Julia中使用jupyter笔记本,运行单元格可以使用shift + enter,也可以使用运行按钮。 运行第一个单元格可以看到,显示了最后一行的值,我们可以用分号抑制输出,尝试执行第二个单元格,可以发现没有输出。 …

Qto_ProjectionElementBaseQuantities

Qto_ProjectionElementBaseQuantities 投影图元基本数量:投影图元的所有引用的定义通用的基本数量。NameTypeDescriptionArea Q_AREAFlche悬臂、壁架或其他杆的区域,是壁架等的观察表面,或天花板结构等的基础区域。Area立面视图(对于墙投影)或底层视图(对于楼板投影)所查…

IntelliJ IDEA Maven 项目的依赖分析

在一个 maven 的项目中,我们需要知道我们的项目中使用的包可能有哪些冲突。 这个在 IntelliJ IDEA 中提供了贴心的查看。 选择 Maven 项目中的分析依赖。随后,IntelliJ IDEA 将会打开一个依赖分析的标签页。 在这个标签页中,我们可以看到我们项目中导入的依赖有哪些冲突,并…

光刻机与芯片制造技术杂谈

光刻机与芯片制造技术杂谈 单价1.2亿美元的光刻机 在中国与美国的贸易冲突中,半导体领域是其中的一个重点,它是《中国制造2025》路线图中第一个要解决的高科技领域,也是中国制造业目前的薄弱之处,在半导体设计、制造到封装三个环节中,半导体制造是国内急需突破的领域,但它…

Cesium中的坐标转换

Cesium中的坐标转换 1 Cesium中相关坐标系 1.1 WGS84坐标系 ​ cesium假设wgs84坐标系构成地球球体是xy平面的正圆,z轴稍微小一点扁椭球 ​ x轴垂直纸面向上,wgs84坐标系定义的x,y平面圆是正圆,半径是6378137,xz或者yz的圆是椭圆,z轴的半径是:6356752.3142451793 ​ WGS…

元素类型

元素类型 块元素:有display:block/display:list-item属性 特点: 1.默认情况下会独占一行,为矩形区域 2.可以定义自己的宽度和高度3.一边作为其他元素的容器 div p ul ol li dt dl dd h1-h6 行内元素:有display:inline元素 1.横着排2.不能定义宽高3.只有个别行…

MarkDown常用语法-231012

标题 # 一级标题 ## 二级标题 ### 三级标题 …… 字体样式斜体 粗体 粗斜体 清除线引用小于号表示引用图片超链接 博客园链接 列表 有序列表有序列表1 有序列表2无序列表无序列表1 无序列表2 ……代码

基于亚奈奎斯特采样和SOMP算法的平板脉冲响应空间插值matlab仿真

1.算法运行效果图预览 2.算法运行软件版本 matlab2022a3.算法理论概述平板脉冲响应(Pulse Response)是通信和雷达等领域中的重要参数,它描述了信号在空间中传播的特性。在现实应用中,获取完整的脉冲响应通常是耗时且昂贵的。基于亚奈奎斯特采样和SOMP算法的平板脉冲响应空…

Spring Cloud 2023 新特性 同步网关

网关不支持传统 Servlet 容器 Spring Cloud Gateway 需要运行在提供的 Netty 运行时。它不能在传统的 Servlet 容器中工作,也不能在构建为 WAR 时工作。WebFlux 使用了异步非阻塞的编程模型,相较于传统的 MVC Servlet 需要理解和适应新的编程范式和响应式编程概念,因此学习曲…

Arrays、Lambda

Array.sort() 对对象进行排序Lambda

简单认识主板供电

主板供电的简单概括 日常我们,只需要将CPU供电插槽和ATX主板供电插槽插上,开机,我们就知道主板上的每个部位就会有电。 而主板上大部分硬件都是低电压,高电流。 +12V的 PCI-E插槽、散热风扇、12V RGB。 +5V 的 USB、I/0外设、5V ARGB。 +3.3V的 PCI-E插槽、M.2 SSD。 注:台…

表单验证案例(附源码)

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>用户注册</title><style>body {f…

查询数据库慢排查、获取当前数据库连接数,sql执行很快但是日志记录接口确很慢

获取当前数据库连接数@Resourceprivate DruidDataSource druidDataSource;int activeCount = druidDataSource.getActiveCount();int activePeak = druidDataSource.getActivePeak();LOG.info("当前连接数:{},最高峰值连接数:{}",activeCount,activePeak); 根据日志查…

第一次作业

这个作业属于 https://edu.cnblogs.com/campus/zjlg/23rjjsjc 这个作业的目标是:进行自我介绍、自我评估和对课程的期待 姓名-学号:邱诗杰-2021330361005这个作业属于 https://edu.cnblogs.com/campus/zjlg/23rjjsjc 这个作业的目标是:进行自我介绍、自我评估和对课程的期待…
推荐文章