您的位置:首页 > 大数据 > 人工智能

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

2013-01-04 13:43 471 查看
命名的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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: