socket实现进程间通信

socket实现进程间通信
2011年05月27日
  使用socket实现进程间通信:(UNIX domain中面向连接通信)
  使用套接字除了可以实现网络间不同主机间的通信外,还可以实现同一主机的不同进程间的通信,且建立的通信是双向的通信。
  man unix内容如下:
  NAME( 名称)
  unix, PF_UNIX, AF_UNIX, PF_LOCAL, AF_LOCAL ? 用于本地内部进程通讯的套接 字。
  SYNOPSIS( 总览 )
  #include
  #include
  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
  #include
  #include
  #include
  #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[1024];
  int len;
  struct sockaddr_un clt_addr;
  struct sockaddr_un srv_addr;
  listen_fd=socket(PF_UNIX,SOCK_STREAM,0);
  if(listen_fdsocket函数创建通信所需的套接字,然后,调用connect函数来连接服务器,在成功建立连接后,通过调用write函数向服务器发送指定的消息。
  client代码:c_unix.c
  //c_unix.c
  #include
  #include
  #include
  #include
  #define UNIX_DOMAIN "/tmp/UNIX.domain"
  int main(void)
  {
  int connect_fd;
  int ret;
  char snd_buf[1024];
  int i;
  static struct sockaddr_un srv_addr;
  //creat unix socket
  connect_fd=socket(PF_UNIX,SOCK_STREAM,0);
  if(connect_fd<0)
  {
  perror("cannot create communication socket");
  return 1;
  }
  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==-1)
  {
  perror("cannot connect to the server");
  close(connect_fd);
  return 1;
  }
  memset(snd_buf,0,1024);
  strcpy(snd_buf,"message from client");
  //send info server
  for(i=0;i<4;i++)
  write(connect_fd,snd_buf,sizeof(snd_buf));
  close(connect_fd);
  return 0;
  }
  编译运行:
  # ./s_unix &
  [1] 11664
  # ./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
  #
  当运行s_unix程序后,该程序将处于监听状态。这时,可以通过netstat命令查看程序运行情况,s_unix的套接字类型为流套接字,并处于监听状态。
  #
  # ./s_unix &
  [1] 12056
  # 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
  #
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值