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. Oracle常用基础语句(杂)

    打开服务 WIN + R services.msc 登录 --方法1 --WIN + R --CMD sqlplus / as sysdba --方法2,常用 --WIN + R --CMD --&q ...

  2. Linux虚拟机常用命令

    参考原文链接:(https://blog.csdn.net/fanyun_01/article/details/51083585) 一.Linux虚拟机常用命令 # virsh list //查看已打 ...

  3. BZOJ4698 SDOI2008Sandy的卡片(后缀自动机)

    差分后即求多串LCS.先考虑两个串怎么做.对第一个串建SAM,第二个串在上面跑即可,任意时刻走到的节点表示的都是第二个串的当前前缀在第一个串中出现的最长的后缀,具体计算长度时每走一个字符长度+1,跳f ...

  4. MySQL SELECT表达式的执行顺序是从左往右依次执行

    例子如下:(确保这几个变量都是初次使用,因为mysql的用户自定义变量会在整个连接session中存在) ,,; +--------+-------+---------+-------+ | +--- ...

  5. ubantu18.04 配置nginx与uwsgi(前后端分离)

    ubantu18.04 配置nginx与uwsgi   一.首先先安装nginx静态服务 先更新 sudo apt-get update 1.安装gcc g++的依赖库 sudo apt-get in ...

  6. node express4 + 前端自动刷新

    官网快速生成:http://www.expressjs.com.cn/starter/generator.html 1.安装  express 1.应用生成器工具 express-generator  ...

  7. vue+scss动态改变主题颜色

    1.新建.scss后缀公用文件,放在assets或者其他地方都可以 /*需要切换的颜色变量*/ $color-primary1:#1776E1; /* 更换的颜色 */ $color-primary2 ...

  8. LeetCode 【1】 Two Sum --001

    5月箴言 住进布达拉宫,我是雪域最大的王.流浪在拉萨街头,我是世间最美的情郎.—— 仓央嘉措 从本周起每周研究一个算法,并以swift实现之 001 -- Two Sum (两数之和) 题干英文版: ...

  9. 部署在SAP Cloud Platform CloudFoundry环境的应用如何消费SAP Leonardo机器学习API

    Jerry的前一篇文章 如何在Web应用里消费SAP Leonardo的机器学习API 里介绍的例子是Neo测试环境的Web应用消费sandbox版本的机器学习API,url如下: https://s ...

  10. rarcrack破解rar密码

    kail系统里没有rarcrack工具,需要先在linux安装rarcrack,安装方式如下:apt-get install rarcrack可以对设置密码的压缩包zar直接进行破解,不用字典,直接进 ...