对命名的Unix Domain Socket的认识(一)

 命名的Unix Domain Socket,是相对于未命名的Unix Domain Socket(socketpair)而言的。Unix Domain Socket 主要用于进程间通信,和网络Socket 相比它不依赖于具体的网络协议。它可以将应用层的数据从一个进程拷贝到另一个进程。它主要分为面向流和面向数据包两种模式(类似于TCP和UDP)。
 命名的Unix Domain Socket 需要绑定到一个地址上,只是这个地址不是主机地址,而是一个文件路径,相关结构体是struct sockaddr_un(网络Socket是struct sockaddr_in)。
 具体实现流程如下:
 1.服务端: 创建Socket->绑定Socket->监听Socket->接收客户端连接->接收/发送数据
 2.客户端: 创建Socket->绑定Socket->连接服务端Socket->发送/接收数据
 命名的Unix Domain Socket 的address family 是AF_UNIX,它并不需要IP地址和端口号。它的地址就是一个具体的文件的路径,其客户端也需要绑定(调用bind函数)让服务端识别客户端。
 一般而言,客户端绑定时的文件名称为客户端所在进程的进程号,这样有利于唯一标识该进程。
 服务端和客户端在绑定时,Socket 绑定的文件如果已经存在,那么绑定就会失败,在绑定前,可以将对应文件删除。
 简单而言,命名的Unix Domain Socket 就是将Socket 绑定到了一个文件上。具体实例如下,这个实例没有具体的数据交互。
 服务端 server.c
  #include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <stddef.h>
#define NAME "/home/test/testsocket.socket"
int main(void){
int sd,cd,result,sin_size;
struct sockaddr_un un;
sd=socket(AF_UNIX,SOCK_STREAM,0);
if(sd==-1){
printf("create unix domain socket failed\n");
return 0;
}
printf("create unix domain socket successfully!\n");
unlink(NAME);
memset(&un,0,sizeof(struct sockaddr_un));
un.sun_family=AF_UNIX;
strcpy(un.sun_path,NAME);
int len=offsetof(struct sockaddr_un,sun_path)+strlen(NAME);
if(bind(sd,(struct sockaddr *)&un,len)<0){

printf("bind unix domain socket error!\n");

return 0;
}
printf("bind unix domain socket successfully!\n");
if(listen(sd,10)<0){
printf("listen unix domain socket error!]n");
return 0;
}
printf("listen unix domain socket successfully!\n");
while(1){
   sin_size=sizeof(struct sockaddr_un);
   result=accept(sd,(struct sockaddr *)&un,&sin_size);
   if(result<0){
   return -1;
   }  
   printf("accept client request\n");
   close(result);
}
close(sd);
return 0;
}
 客户端 client.c
 #include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stddef.h>
#include <errno.h>
#define NAME "/home/test/testsocket.socket"
#define CLI_PATH "/home/test/"
#define CLI_PERM S_IRWXU
int main(void){
int cd,length;
struct sockaddr_un un;
cd=socket(AF_UNIX,SOCK_STREAM,0);
if(cd==-1){
printf("create unix domain socket fail\n");
return -1;
}
printf("create client unix domain socket successfully\n");
memset(&un,0,sizeof(un));
un.sun_family=AF_UNIX;
 sprintf(un.sun_path, "%s%05d", CLI_PATH, getpid());
length=offsetof(struct sockaddr_un,sun_path)+strlen(un.sun_path);
unlink(un.sun_path);
if(bind(cd,(struct sockaddr *)&un,length)<0){
printf("bind client unix domain socket fail\n");
return -1;
}
printf("bind client unix domain socket successfully\n");
printf("sun_path is %s\n",un.sun_path);
if(chmod(un.sun_path,CLI_PERM)<0){
printf("chmod fail \n");
return -1;
}
memset(&un,0,sizeof(un));
un.sun_family=AF_UNIX;
strcpy(un.sun_path,NAME);
length=offsetof(struct sockaddr_un,sun_path)+strlen(un.sun_path);

if(connect(cd,(struct sockaddr *)&un,length)==-1){
  printf("connect unix domain socket failed\n");
  return -1;
}
printf("connect remote socket successfully\n");
close(cd);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值