您的位置:首页 > 编程语言

关于UNIX Domain Socket 编程

2015-06-25 14:26 393 查看
       进程间通信,通讯机制很快会从大脑中跑出一连串方法出来:共享内存、管道、有名管道、信号量、套接字(socket)等。提到socket 大家很快会想到的是 address family
为AF_INET  ,type为SOCK_DGRAM或SOCK_STREAM 。还有一种接触少的没有接触的人很多时候会忽略:UNIX Domain Socket 。解决同样的通信问题,但在效率上与可靠性上它(UNIX
Domain Socket)会略胜一筹:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。 这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX
Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。

 
       UNIX Domain Socket 的type同样可以选择SOCK_DGRAM或SOCK_STREAM ,address family 指定为AF_UNIX,protocol参数仍然指定为0即可。UNIX
Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口 号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存 在,则bind()错误返回。int fd_server_listen(const char *filepath)// src >> "/var/fd.socket"
{
int sockfd;
struct sockaddr_un unix_addr;

/* create a Unix domain stream socket */
if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
printf("domain socket server initialized fail!\n");
return -1;
}

/* in case it already exists */
unlink(filepath);

/* fill in socket address structure */
memset(&unix_addr, 0, sizeof(unix_addr));
unix_addr.sun_family = AF_UNIX;
strcpy(unix_addr.sun_path, filepath);

/* bind the name to the descriptor */
if(bind(sockfd, (struct sockaddr *)&unix_addr, SUN_LEN(&unix_addr)) < 0)
{
printf("domain socket server bind fail!\n");
goto error;
}

if(chmod(filepath, S_IRUSR|S_IWUSR) < 0)
{
printf("chmod fail:%s\n", filepath);
goto error;
}

/* tell kernel we're a server */
if(listen(sockfd, 10) < 0)
{
printf("domain socket server listen fail!\n");
goto error;
}

return sockfd;

error:
close(sockfd);
return -1;
}
int client_fd = accept(sockfd, NULL, NULL);
关于编程客户端,有关小小的细节注意下,就是socket的相应的路径需要相同例如:HYCGI_SERVSOCK_PATH
的路径应该是服务端src一样的。
int InitSocket(int *cli_sockfd)
{
struct sockaddr_un address;
int sockfd;
int len;

/*创建socket,AF_UNIX通信协议,SOCK_STREAM数据方式*/
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
{
printf("InitSocket ::failed");
return 1;
}

//addr
address.sun_family = AF_UNIX;
strcpy (address.sun_path, HYCGI_SERVSOCK_PATH);
len = OFFSETOF(struct sockaddr_un, sun_path) + strlen(HYCGI_SERVSOCK_PATH);

/*向服务器发送连接请求*/
if (-1 == connect (sockfd, (struct sockaddr *)&address, len) )
{
close(sockfd);
char buf[64];
sprintf(buf,"InitSocket::connect errno = %d",errno);
printf("%s"buf);
return 2;
}

*cli_sockfd = sockfd;

return 0;
}关于UNIX
Domain Socket 编程,以上是最基础的过程,个人感觉无论是管道还是这个,还是共享内存,抓住编程的初衷:数据的有效传递。相关的,对于多个线程间如何跟服务端通信,还需要设置相关定制协议即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息