socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机
制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过
loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协
议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷
贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯
设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,
但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。
UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越
性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX
Domain Socket通讯的。
使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创
建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或

SOCK_STREAM,protocol参数仍然指定为0即可。
UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体
sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地
址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果
调用bind()时该文件已存在,则bind()错误返回。
以下程序将UNIX Domain socket绑定到一个地址。

size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
#define offsetof(TYPE, MEMBER) ((int)&((TYPE *)0)->MEMBER)

server

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#define QLEN 10
/*
* Create a server endpoint of a connection.
* Returns fd if all OK, <0 on error.
*/
int serv_listen(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;
/* create a UNIX domain stream socket */
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return(-1);
unlink(name); /* in case it already exists 否则bind的时候会出错*/
/* fill in socket address structure */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
/* bind the name to the descriptor 会创建name*/
if (bind(fd, (struct sockaddr *)&un, len) < 0) {
rval = -2;
goto errout;
}
if (listen(fd, QLEN) < 0) { /* tell kernel we're a server */
rval = -3;
goto errout;
}
return(fd);
errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
int serv_accept(int listenfd, uid_t *uidptr)
{
int clifd, len, err, rval;
time_t staletime;
struct sockaddr_un un;
struct stat statbuf;
len = sizeof(un);
if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0)
return(-1); /* often errno=EINTR, if signal caught */
/* obtain the client's uid from its calling address */
len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */
un.sun_path[len] = 0; /* null terminate */
if (stat(un.sun_path, &statbuf) < 0) {
rval = -2;
goto errout;
}
if (S_ISSOCK(statbuf.st_mode) == 0) {
rval = -3; /* not a socket */
goto errout;
}
if (uidptr != NULL)
*uidptr = statbuf.st_uid; /* return uid of caller */
unlink(un.sun_path); /* we're done with pathname now */
return(clifd);
errout:
err = errno;
close(clifd);
errno = err;
return(rval);
}
int main(void)
{
int lfd, cfd, n, i;
uid_t cuid;
char buf[1024];
lfd = serv_listen("foo.socket");
if (lfd < 0) {
switch (lfd) {
case -3:perror("listen"); break;
case -2:perror("bind"); break;
case -1:perror("socket"); break;
}
exit(-1);
}
cfd = serv_accept(lfd, &cuid);
if (cfd < 0) {
switch (cfd) {
case -3:perror("not a socket"); break;
case -2:perror("a bad filename"); break;
case -1:perror("accept"); break;
}
exit(-1);
}
while (1) {
r_again:
n = read(cfd, buf, 1024);
if (n == -1) {
if (errno == EINTR)
goto r_again;
}
else if (n == 0) {
printf("the other side has been closed.\n");
break;
}
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
write(cfd, buf, n);
}
close(cfd);
close(lfd);
return 0;
}

client

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#define CLI_PATH "/var/tmp/" /* +5 for pid = 14 chars */
/*
* Create a client endpoint and connect to a server.
* Returns fd if all OK, <0 on error.
*/
int cli_conn(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;
/* create a UNIX domain stream socket */
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return(-1);
/* fill socket address structure with our address */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid());
len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
unlink(un.sun_path); /* in case it already exists */
if (bind(fd, (struct sockaddr *)&un, len) < 0) {
rval = -2;
goto errout;
}
/* fill socket address structure with server's address */
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
if (connect(fd, (struct sockaddr *)&un, len) < 0) {
rval = -4;
goto errout;
}
return(fd);
errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
int main(void)
{
int fd, n;
char buf[1024];
fd = cli_conn("foo.socket");
if (fd < 0) {
switch (fd) {
case -4:perror("connect"); break;
case -3:perror("listen"); break;
case -2:perror("bind"); break;
case -1:perror("socket"); break;
}
exit(-1);
}
while (fgets(buf, sizeof(buf), stdin) != NULL) {
write(fd, buf, strlen(buf));
n = read(fd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, n);
}
close(fd);
return 0;
}

转载于:https://www.cnblogs.com/xiangtingshen/p/10923350.html

Domain Socket本地进程间通信相关推荐

  1. 【进程间通信】Unix domain socket (进程间通信)

    socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket. 虽然网络socket也可用于同一台主机的进程间通讯(通过loo ...

  2. Linux socket本地进程间通信之UDP

    当套接字用于本地通信时,可以使用结构体struct sockaddr_un描述一个本地地址. 1 struct sockaddr_un{ 2 unsigned short sun_family; /* ...

  3. 本地进程间通信(二)--套接字socket

    目录 一.什么是Socket? 二.socket通信流程 Server端 一.创建socket 二.命名socket. 三.绑定 四.监听 五.关闭 Client端 一.创建socket 二.conn ...

  4. Socket编程(C语言实现)—— AF_INET(典型的TCP/IP四层模型的通信过程),AF_UNIX(本地进程间通信)

    1.AF_INET域与Socket通信 其是典型的TCP/IP四层模型的通信过程. (1)接收方与发送方依赖IP和port来标识,即,将本地socket绑定到对应的IP端口上: (2)发送数据时指定对 ...

  5. UNIX Domain Socket(UDS)是什么?同一台主机间进程间通信

    文章目录 概述 流程介绍 概述 Linux下进程通讯方式有很多,比较典型的有套接字,平时比较常用的套接字是基于TCP/IP协议的,适用于两台不同主机上两个进程间通信, 通信之前需要指定IP地址. 但是 ...

  6. Unix domain socket 简介(进程间通信,进程通信)

    Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信.socket 原本是为网络通讯设 ...

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

    目录 unix域套接字(socketpair )通信|socketpair和pipe的区别 socketpair机制 描述 原理 socketpair和pipe的区别 进程间通信-Unix domai ...

  8. linux 系统下使用socket进行本地进程间通信:About AF_LOCAL in Linux

    点击打开链接 一.Unix domain socket Unix domain socket 或者 IPC socket是一种终端,可以使同一台操作系统上的两个或多个进程进行数据通信.与管道相比,Un ...

  9. 【技术应用】java基于UNIX域套接字(unix domain socket)连接mysql数据库

    前言 Unix domain socket 又叫 IPC(inter-process communication 进程间通信)socket,用于实现同一主机上的进程间通信. socket 原本是为网络 ...

最新文章

  1. tensorflow deep_speech2 神经网络结构代码分析
  2. C语言----求解N以内的素数的两种典型方法以及其优化
  3. 七、Java编码字符集和转义符介绍
  4. 阿里重磅开源首款自研科学计算引擎Mars,揭秘超大规模科学计算
  5. Privacy Policy
  6. Bootstrap3 插件的原理
  7. 水晶报表CrystalReports很强大也很简单!
  8. 吴恩达 深度学习 2021版 笔记
  9. 工程制图与计算机绘图实训任务书及参考资料,工程制图与计算机绘图综合实训(12版).doc...
  10. 帅某---考研---高数笔记---汤家凤---第十章向量代数与空间几何
  11. Python爬虫用(Python+Selenium)打开谷歌,IE,火狐浏览器,并访问网页
  12. Python——列表的方法
  13. firefox 浏览器证书问题
  14. [JVM]了断局: “运行时数据区“理论梳理
  15. MediaWiki在Windows安装部署——部署mediawiki
  16. 什么是服务器工程文件格式,Visio找不到数据库建模功能怎么办 VSD文件是什么格式...
  17. 下载vue模板框架并使用
  18. 自监督学习之对比学习
  19. js基础 - 正则表达式的详细介绍以及电子邮件、手机号码的格式举例
  20. 趋势预测方法(一) 多项式拟合(最小二乘法)_函数拟合

热门文章

  1. php修改session生存时间,修改session的过期(生存)时间
  2. Android 项目在Eclipse中的目录结构
  3. Exynos4412 文件系统制作(二)—— 文件系统简介
  4. Windows系统USB转CDC串口驱动限制说明
  5. react学习(43)----react中将一个元素渲染为 DOM
  6. 前端学习(3040):vue+element今日头条管理-上午回顾
  7. [html] Standards模式和Quirks模式有什么区别?
  8. [css] 请描述下你对translate()方法的理解
  9. 前端学习(2198):vuex-state单一状态的理解
  10. 前端学习(1986)vue之电商管理系统电商系统之建立新分支