Domain Socket本地进程间通信
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, )) < )
return(-);
unlink(name); /* in case it already exists 否则bind的时候会出错*/
/* fill in socket address structure */
memset(&un, , 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) < ) {
rval = -;
goto errout;
}
if (listen(fd, QLEN) < ) { /* tell kernel we're a server */
rval = -;
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)) < )
return(-); /* 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] = ; /* null terminate */
if (stat(un.sun_path, &statbuf) < ) {
rval = -;
goto errout;
}
if (S_ISSOCK(statbuf.st_mode) == ) {
rval = -; /* 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[];
lfd = serv_listen("foo.socket");
if (lfd < ) {
switch (lfd) {
case -:perror("listen"); break;
case -:perror("bind"); break;
case -:perror("socket"); break;
}
exit(-);
}
cfd = serv_accept(lfd, &cuid);
if (cfd < ) {
switch (cfd) {
case -:perror("not a socket"); break;
case -:perror("a bad filename"); break;
case -:perror("accept"); break;
}
exit(-);
}
while () {
r_again:
n = read(cfd, buf, );
if (n == -) {
if (errno == EINTR)
goto r_again;
}
else if (n == ) {
printf("the other side has been closed.\n");
break;
}
for (i = ; i < n; i++)
buf[i] = toupper(buf[i]);
write(cfd, buf, n);
}
close(cfd);
close(lfd);
return ;
}
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, )) < )
return(-);
/* fill socket address structure with our address */
memset(&un, , 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) < ) {
rval = -;
goto errout;
}
/* fill socket address structure with server's address */
memset(&un, , 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) < ) {
rval = -;
goto errout;
}
return(fd);
errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
int main(void)
{
int fd, n;
char buf[];
fd = cli_conn("foo.socket");
if (fd < ) {
switch (fd) {
case -:perror("connect"); break;
case -:perror("listen"); break;
case -:perror("bind"); break;
case -:perror("socket"); break;
}
exit(-);
}
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 ;
}
Domain Socket本地进程间通信的更多相关文章
- Unix domain socket
转载:http://www.cnblogs.com/chekliang/p/3222950.html socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是 ...
- 由一个简单需求到Linux环境下的syslog、unix domain socket
本文记录了因为一个简单的日志需求,继而对linux环境下syslog.rsyslog.unix domain socket的学习.本文关注使用层面,并不涉及rsyslog的实现原理,感兴趣的读者可以参 ...
- 【转】PHP实现系统编程(四)--- 本地套接字(Unix Domain Socket)
原文:http://blog.csdn.net/zhang197093/article/details/78143687?locationNum=6&fps=1 --------------- ...
- Android native进程间通信实例-socket本地通信篇之——基本通信功能
导读: 网上看了很多篇有关socket本地通信的示例,很多都是调通服务端和客户端通信功能后就没有下文了,不太实用,真正开发中遇到的问题以及程序稳定性部分没有涉及,代码健壮性不够,本系列(socket本 ...
- socket实现进程间通信(转载)
转自:http://blog.csdn.net/ast_224/article/details/3962221 使用socket实现进程间通信:(UNIX domain中面向连接通信) 使用套接字除了 ...
- ZeroMQ接口函数之 :zmq_ipc – ZMQ本地进程间通信传输协议
ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html ——————————————————————————————————— ...
- [dev][socket] unix domain socket删除socket文件
问题 在使用unix domain socket的时候,bind之后,会在本地路径里 产生一个与path对应的socket文件. 如何正确的在用完socket之后,对其销毁呢? 方案 使用 unlin ...
- Unix domain socket 简介
Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信.socket 原本是为网络通讯设 ...
- Unix domain socket IPC
UNIX Domain socket 虽然网络socket也可用于同一台主机的进程间通讯(通过lo地址127.0.0.1),但是unix domain socket用于IPC更有效率:不需要经过网络协 ...
随机推荐
- 少儿编程 | 01.Scratch 3.0简介
欢迎参加这套Scratch3.0少儿编程课程的学习.本系列课程将通过视频和图文的方式进行(视频制作中,后续会发布).如果喜欢本系列课程,欢迎点击订阅关注或者转发. 这是本系列课程的第一课,主要是给家长 ...
- mongo与spring集合
1.加入lib包,在Maven中 <dependency> <groupId>org.springframework.data</groupId> <arti ...
- Zuma CodeForces - 607B (区间DP)
大意: 给定字符串, 每次删除一个回文子串, 求最少多少次删完. #include <iostream> #include <cstdio> #define REP(i,a,n ...
- IntelliJ Idea清除Open Recent里面的项目列表
2种方法清除IntelliJ Idea 中 Open Recent里面的项目列表 第一种方法: 如下图: Open Recent -> Manage Projects Recent Projec ...
- hdu 4504 dp问题 转化能力不够 对状态的转移也是不够
威威猫系列故事——篮球梦 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...
- 中国5级行政区域MySQL数据库库
爬取国家统计局官网的行政区域数据,包括省市县镇村5个层级,其中港澳地区的数据只有3级;台湾地区4级;包含大陆地区的邮政编码和经纬度信息. 行政划分的总体结构是: 省->市(州)->县(区) ...
- 6.NIO2-Path、Paths、Files
NIO.2 jdk1.7中,java对 NIO 极大的扩展,主要增强的是对文件处理 和 文件系统特性的支持 关于其中一些API的使用 public class TestNIO_2_Path_File ...
- 初识cv
验证码识别的一般套路: 灰度化.图像处理.二值化.选算法.训练.评估调整参数.预测,当然,我在这里二值化与处理的顺序换了一下,灵活处理哈 1 显示图片轮廓 img = cv2.Canny(img,25 ...
- xargs 使用详解
参考转载:https://www.cnblogs.com/f-ck-need-u/p/5925923.html#auto_id_12 xargs 作用:将管道传输过来的stdin进行处理(分割.分批) ...
- nginx负载均衡简单实例
nginx分配服务器策略 1.轮询(默认) 每一个请求按时间顺序逐一分配到不同的祸端服务器,如果后端服务器 down 掉,能自动抵触 2.weight(权重) weight代表权重,默认为1,权重越高 ...