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本地进程间通信的更多相关文章

  1. Unix domain socket

    转载:http://www.cnblogs.com/chekliang/p/3222950.html socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是 ...

  2. 由一个简单需求到Linux环境下的syslog、unix domain socket

    本文记录了因为一个简单的日志需求,继而对linux环境下syslog.rsyslog.unix domain socket的学习.本文关注使用层面,并不涉及rsyslog的实现原理,感兴趣的读者可以参 ...

  3. 【转】PHP实现系统编程(四)--- 本地套接字(Unix Domain Socket)

    原文:http://blog.csdn.net/zhang197093/article/details/78143687?locationNum=6&fps=1 --------------- ...

  4. Android native进程间通信实例-socket本地通信篇之——基本通信功能

    导读: 网上看了很多篇有关socket本地通信的示例,很多都是调通服务端和客户端通信功能后就没有下文了,不太实用,真正开发中遇到的问题以及程序稳定性部分没有涉及,代码健壮性不够,本系列(socket本 ...

  5. socket实现进程间通信(转载)

    转自:http://blog.csdn.net/ast_224/article/details/3962221 使用socket实现进程间通信:(UNIX domain中面向连接通信) 使用套接字除了 ...

  6. ZeroMQ接口函数之 :zmq_ipc – ZMQ本地进程间通信传输协议

    ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html ——————————————————————————————————— ...

  7. [dev][socket] unix domain socket删除socket文件

    问题 在使用unix domain socket的时候,bind之后,会在本地路径里 产生一个与path对应的socket文件. 如何正确的在用完socket之后,对其销毁呢? 方案 使用 unlin ...

  8. Unix domain socket 简介

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

  9. Unix domain socket IPC

    UNIX Domain socket 虽然网络socket也可用于同一台主机的进程间通讯(通过lo地址127.0.0.1),但是unix domain socket用于IPC更有效率:不需要经过网络协 ...

随机推荐

  1. git 去除版本控制

    git会进入当前文件目录, 然后执行如下命令: find . -name ".git" | xargs rm -Rf 该项目就会去除git的版本控制了.再修改的话也不会影响git的 ...

  2. Java InsertionSort

    Java InsertionSort /** * <html> * <body> * <P> Copyright 1994-2018 JasonInternatio ...

  3. Hackthebox--------irked

    菜鸟一枚,大佬轻喷!! Web页面就一张表情图和一句IRC is almost working!(是irc服务么??!!) 查看图片信息,貌似图片没这么简单.... 果然没这么简单,不行,得想办法得到 ...

  4. 字蛛webfont 安装及使用方法

    先安装nodejs和git,比如放在D:/nodejs/  文件夹 cmd 进入该文件夹,安装npm install express 安装 npm install font-spider -g 安装  ...

  5. js的数据类型、函数、流程控制及变量的四种声明方式

    运算符 基本运算符 加 + 减 - 乘 * 除 / 取余 % 自增 ++ eg: 1++ 或 ++1 自减 -- eg: 1-- 或 --1 注:++或--写在前面表示优先级最高,先进行自增或者自减 ...

  6. umi model 注册

    model 分两类,一是全局 model,二是页面 model.全局 model 存于 /src/models/ 目录,所有页面都可引用:页面 model 不能被其他页面所引用. 规则如下: src/ ...

  7. SpringDataJPA第二天讲义

    第1章     Spring Data JPA的概述 1.1    Spring Data JPA概述 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的 ...

  8. python 链接impala执行SQL

    项目中用python来链接impala数据库最常见,一个简单的链接,获取结果. #!/usr/bin/python # -*- coding:utf-8 -*- from impala.dbapi i ...

  9. 案例:selenium实现登录百度(如有验证码,需要手动输入)

    func.py https://www.cnblogs.com/andy9468/p/10899508.html baidu_login.py中(如有验证码,需要手动输入) # 导入webdriver ...

  10. 单选框 RadioButton

    activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...