转自:http://blog.csdn.net/ast_224/article/details/3962221

使用socket实现进程间通信:(UNIX domain中面向连接通信)

使用套接字除了可以实现网络间不同主机间的通信外,还可以实现同一主机的不同进程间的通信,且建立的通信是双向的通信。
    man unix内容如下:

NAME( 名称)
    unix, PF_UNIX, AF_UNIX, PF_LOCAL, AF_LOCAL ? 用于本地内部进程通讯的套接字。

SYNOPSIS( 总览 )
    #include <sys/socket.h>
    #include <sys/un.h>

unix_socket = socket(PF_UNIX, type, 0);
    error = socketpair(PF_UNIX, type, 0, int *sv);
DESCRIPTION( 描述 )
   
PF_UNIX (也称作 PF_LOCAL ) 套接字族用来在同一机器上的提供有效的进程间通讯.Unix 套接字可以是匿名的(由
socketpair(2)创建), 也可以与套接字类型文件相关联. Linux 还支持一种抽象名字空间, 它是独立于文件系统的.
    有效的类型有: SOCK_STREAM 用于面向流的套接字, SOCK_DGRAM 用于面向数据报的套接字,其可以保存消息界限. Unix 套接字总是可靠的,而且不会重组数据报.
    Unix 套接字支持把文件描述符或者进程的信用证明作为数据报的辅助数据传递给 其它进程.
ADDRESS FORMAT( 地址格式 )
   
unix 地址定义为文件系统中的一个文件名或者抽象名字空间中的一个单独的字符串. 由 socketpair(2)
创建的套接字是匿名的.对于非匿名的套接字,目标地址 可使用 connect(2) 设置. 本地地址可使用 bind(2) 设置.
当套接字连接上而且它没有一个本地地址时, 会自动在抽象名字空间中生成一个唯一的地址.
    #define UNIX_PATH_MAX   108

struct sockaddr_un {
    sa_family_t     sun_family;     /* AF_UNIX */
    char    sun_path[UNIX_PATH_MAX];        /* 路径名 */
    };
   
sun_family 总是包含 AF_UNIX. sun_path 包含空零结尾的套接字在文件系统中的路径名. 如果 sun_path
以空零字节开头,它指向由 Unix 协议模块维护的抽象名字空间. 该套接字在此名字空间中的地址由 sun_path 中的剩余字节给定.
注意抽象名字空间的名字都不是空零终止的.
SOCKET OPTIONS( 套接字选项 )
    由 于 历 史 原 因,
这些套接字选项通过 SOL_SOCKET 类型确定, 即使它们是 PF_UNIX 指定的. 它们可以由 setsockopt(2) 设置.
通过指定 SOL_SOCKET 作 为套接字族用 getsockopt(2) 来读取.
    SO_PASSCRED 允许接收进程辅助信息发送的信用证明. 当设置了该选项且套接字 尚未连接时, 则会自动生成一个抽象名字空间的唯一名字. 值为一个整数布尔标 识.
ANCILLARY MESSAGES( 辅助信息 )
   
由 于 历 史 原 因, 这些辅助信息类型通过 SOL_SOCKET 类型确定, 即使它们是 PF_UNIX 指定的. 要发送它们,
可设置结构 cmsghdr 的 cmsg_level 字 段 为 SOL_SOCKET, 并 设 置 cmsg_type 字段为其类型.
要获得更多信息, 请参看 cmsg(3).
    SCM_RIGHTS
    为其他进程发送或接收一套打开文件描述符. 其数据部分包含一个文件 描述符的整型数组. 已传文件描述符的效果就如它们已由 dup(2) 创建 过一样.
    SCM_CREDENTIALS
    发送或者接收 unix 信用证明. 可用作认证.信用证明传送 以 struct ucred 辅助信息的形式传送.
    struct ucred {
    pid_t   pid;     /* 发送进程的进程标识 */
    uid_t   uid;     /* 发送进程的用户标识 */
    gid_t   gid;     /* 发送进程的组标识 */
    };
   
发 送者确定的信用证明由内核检查. 一个带有有效用户标识 0 的进程允许指定 不与其自身值相匹配的值.发送者必须确定其自身的进程 标 识(
除非它带 有 CAP_SYS_ADMIN), 其 用 户 标识,有效用户标识或者设置用户标识(除非它带有CAP_SETUID),
以及其组标识,有效组标识或者 设 置 组 标 识( 除非它带有CAP_SETGID). 为 了 接 收 一 条 struct ucred
消息,必须在套接字上激活 SO_PASSCRED 选项.
ERRORS( 错误 )
    ENOMEM
        内存溢出.
   
    ECONNREFUSED
        connect(2) 调用了一个未在监听的套接字对象. 这可能发生在远程套 接字不存在或者文件名不是套接字的时候.
    EINVAL
        传递了无效参数. 通常的产生原因是已传地址的 sun_type 字 段的 AF_UNIX 设置丢失, 或者套接字对应用的操作处于无效状态.
    EOPNOTSUPP
        在非面向流的套接字上调用了流操作,或者试图使用出界的数据选项.
    EPROTONOSUPPORT
        传递的协议是非 PF_UNIX 的.
    ESOCKTNOSUPPORT
        未知的套接字类型.
    EPROTOTYPE
        远程套接字与本地套接字类型不匹配 (SOCK_DGRAM 对SOCK_STREAM).
    EADDRINUSE
        选择的本地地址已经占用,或者文件系统套接字对象已经存在.
    EISCONN
        在 一个已经连接的套接字上调用 connect(2) 或者指定的目标地址在一 个已连接的套接字上.
    ENOTCONN
        套接字操作需要一个目的地址,但是套接字尚未连接.
    ECONNRESET
        远程套接字意外关闭.
    EPIPE
        远程套接字在一个流套接字上关闭了.如果激活,会同时发送一个 SIGPIPE 标识.这可以通过传递 MSG_NOSIGNAL 标识给 sendmsg(2) 或者 recvmsg(2) 来避免.
    EFAULT
        用户内存地址无效.
    EPERM
        发送者在 struct ucred 中传递无效的信用证明.
    当生成一个文件系统套接字对象时, 可能会由通用套接层或者文件系统产生其它错误. 要获得更多信息,可参见合适的手册页.

实践:

使用套接字在UNIX域内实现进程间通信的服务端程序。首先,程序通过调用socket函数,建立了监听连接的套接字,然后调用bind函数,将套接字与
地址信息关联起来。调用listen函数实现对该端口的监听,当有连接请求时,通过调用accept函数建立与客户机的连接,最后,调用read函数来读
取客户机发送过来的消息,当然也可以使用recv函数实现相同的功能。

server代码:s_unix.c

    //s_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
int main(void)
{
socklen_t clt_addr_len;
int listen_fd;
int com_fd;
int ret;
int i;
static char recv_buf[];
int len;
struct sockaddr_un clt_addr;
struct sockaddr_un srv_addr;
listen_fd=socket(PF_UNIX,SOCK_STREAM,);
if(listen_fd<)
{
perror("cannot create communication socket");
return ;
} //set server addr_param
srv_addr.sun_family=AF_UNIX;
strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-);
unlink(UNIX_DOMAIN);
//bind sockfd & addr
ret=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
if(ret==-)
{
perror("cannot bind server socket");
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}
//listen sockfd
ret=listen(listen_fd,);
if(ret==-)
{
perror("cannot listen the client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}
//have connect request use accept
len=sizeof(clt_addr);
com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len);
if(com_fd<)
{
perror("cannot accept client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}
//read and printf sent client info
printf("/n=====info=====/n");
for(i=;i<;i++)
{
memset(recv_buf,,);
int num=read(com_fd,recv_buf,sizeof(recv_buf));
printf("Message from client (%d)) :%s/n",num,recv_buf);
}
close(com_fd);
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}

使用套接字在UNIX域内实现进程间通信的客户端程序。相比服务端的程序,客户段较为简单。程序首先通过调用socket函数创建通信所需的套接字,然后,调用connect函数来连接服务器,在成功建立连接后,通过调用write函数向服务器发送指定的消息。

client代码:u_unix.c

    //c_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
int main(void)
{
int connect_fd;
int ret;
char snd_buf[];
int i;
static struct sockaddr_un srv_addr;
//creat unix socket
connect_fd=socket(PF_UNIX,SOCK_STREAM,);
if(connect_fd<)
{
perror("cannot create communication socket");
return ;
}
srv_addr.sun_family=AF_UNIX;
strcpy(srv_addr.sun_path,UNIX_DOMAIN);
//connect server
ret=connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
if(ret==-)
{
perror("cannot connect to the server");
close(connect_fd);
return ;
}
memset(snd_buf,,);
strcpy(snd_buf,"message from client");
//send info server
for(i=;i<;i++)
write(connect_fd,snd_buf,sizeof(snd_buf));
close(connect_fd);
return ;
}

编译运行:

[root@localhost liuxltest]# ./s_unix &
[1] 11664
[root@localhost liuxltest]# ./c_unix &

=====info=====
Message from client (1024)) :message from client
Message from client (1024)) :message from client
Message from client (1024)) :message from client
Message from client (1024)) :message from client
[2] 11665
[1]-  Done                    ./s_unix
[2]+  Done                    ./c_unix
[root@localhost liuxltest]#

当运行s_unix程序后,该程序将处于监听状态。这时,可以通过netstat命令查看程序运行情况,s_unix的套接字类型为流套接字,并处于监听状态。
[root@localhost liuxltest]#
[root@localhost liuxltest]# ./s_unix &
[1] 12056
[root@localhost liuxltest]# netstat -an |grep /tmp
unix  2      [ ACC ]     STREAM     LISTENING     64014  /tmp/ssh-CekOJ11069/agent.11069
unix  2      [ ACC ]     STREAM     LISTENING     6216   /tmp/.font-unix/fs7100
unix  2      [ ACC ]     STREAM     LISTENING     62042  /tmp/ssh-XOCgkr9439/agent.9439
unix  2      [ ACC ]     STREAM     LISTENING     62316  /tmp/ssh-mojoaQ9648/agent.9648
unix  2      [ ACC ]     STREAM     LISTENING     65267  /tmp/UNIX.domain
unix  2      [ ACC ]     STREAM     LISTENING     65210  /tmp/ssh-NlKtA12012/agent.12012
[root@localhost liuxltest]#

socket实现进程间通信(转载)的更多相关文章

  1. 理解Socket编程【转载】

    “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...

  2. 细说linux IPC(一):基于socket的进程间通信(上)

        [版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途]     在一个较大的project其中 ...

  3. socket.io(转载)

    socket.io 中文手册,socket.io 中文文档转载于:http://www.cnblogs.com/xiezhengcai/p/3956401.html 服务端 io.on(‘connec ...

  4. Socket编程——(转载)

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠so ...

  5. Socket桥(转载)

    最好方案:使用haproxy 或者nginx转发.自己写程序性能和监控难保证,推荐使用开源软件替代. 源地址为:http://baishaobin2003.blog.163.com/blog/stat ...

  6. linux下socket编程-进程间通信

    一.什么是Socket Socket接口是TCP/IP网络通信的API,Socket接口定义了许多函数或例程,可以用它们来开发TCP/IP网络上的应用程序. Socket类型有两种:流式Socket ...

  7. win32下Socket编程(转载)

    在网上找了很多的资料,现将这些资料整合起来,详细介绍一下VC下的socket编程,并提供一个服务器客户端具体的实例.希望对您有所帮助 一.原理部分 (个人觉得这篇写的可以,所以转与此,原文地址:htt ...

  8. java Socket(详解)转载

    在客户/服务器通信模式中, 客户端需要主动创建与服务器连接的 Socket(套接字), 服务器端收到了客户端的连接请求, 也会创建与客户连接的 Socket. Socket可看做是通信连接两端的收发器 ...

  9. Java Socket 通信实例 - 转载

    基于Tcp协议的简单Socket通信实例(JAVA)   好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些 ...

随机推荐

  1. 【2018 Multi-University Training Contest 2】

    01: 02: 03: 04:https://www.cnblogs.com/myx12345/p/9394511.html 05: 06: 07:https://www.cnblogs.com/my ...

  2. BZOJ4580: [Usaco2016 Open]248

    n<=248个数字,可以进行这样的操作:将相邻两个相同的数字合并成这个数字+1,求最大能合成多少. f(i,j)--区间i到j能合成的最大值,f(i,j)=max(f(i,k)+1),f(i,k ...

  3. msp430入门编程46

    msp430中C语言的人机交互--基于状态机菜单

  4. 前端学习之- Ajax

    Ajax:页面不做刷新,直接将数据悄悄提交到后台,然后通过回调函数处理返回结果. $.Ajax({ # 提交到后台 url:'/host', # 提交到哪里 type:'POST' # 提交方式 da ...

  5. UVAlive 3026 KMP 最小循环节

    KMP算法: 一:next数组:next[i]就是前面长度为i的字符串前缀和后缀相等的最大长度,也即索引为i的字符失配时的前缀函数. 二:KMP模板 /* pku3461(Oulipo), hdu17 ...

  6. spring-boot-starter-data-redis与spring-boot-starter-redis两个包的区别

    spring-boot-starter-data-redis: <?xml version="1.0" encoding="UTF-8"?> < ...

  7. 解决WIN7下VMWARE虚拟机无法上网问题

    一.Win7 虚拟机centos NAT联网 链接地址:http://www.cr173.com/html/19808_1.html,也不知道是哪位大神弄的,实践过,可以使用,但是重启之后却不能用了, ...

  8. [RxJS] Implement RxJS `switchMap` by Canceling Inner Subscriptions as Values are Passed Through

    switchMap is mergeMap that checks for an "inner" subscription. If the "inner" su ...

  9. Win7 本地打印后台处理程序服务没有运 怎么办

    找到名为Print Spooler的服务,启动类型改为自动,服务状态改为启动即可.

  10. performSelector调用和直接调用的区别

    今天在准备出笔试题的过程中随便搜了一下其他的笔试题,看到其中一个就是关于performSelector与直接调用的区别. 个人感觉这其实是一个陷阱题,因为大部分应用场景下,用哪一种都可以,可以说是没有 ...