简介
unix域套接字用于在同一台机器上运行的进程之间的通信。虽然因特网域套接字可用于同一目的,但是unix域套接字效率更高。unix域套接字仅仅复制数据;它们并不执行协议处理,不需要添加或删除网络报头,无需计算校验和,不要产生顺序号,无需发送确认报文。
unix域套接字的地址由sockaddr_un结构表示。sockaddr_un结构按下列形式定义在头文件<sys/un.h>中
structsockaddr_un{
sa_family_t sun_family; /*AF_UNIX */
char sun_path[108]; /* pathname */
};
但是在FreeBSD等其他操作系统中,sockaddr_un结构定义如下:
structsockaddr_un{
unsignedchar sun_len; /* length including null */
sa_family_t sun_family; /*AF_UNIX */
char sun_path[104]; /* pathname */
};
sockaddr_un结构的sun_path成员包含一路径名。当我们将一个地址绑定至unix域套接字时,系统用该路径名创建一类型为S_IFSOCK的文件。该文件仅用于向客户进程告知套接字名字。该文件不能打开,也不能由应用程序用于通信。
如果当我们试图绑定地址时,该文件已存在,那么bind请求会失败。关闭套接字时,并不自动删除该文件,所以必须确保在应用程序终止前,对该文件执行解除链接操作。
示例程序
服务端
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
#include<unistd.h>
#include<errno.h>
#include<sys/socket.h>
#include<sys/un.h>
#definePATH "/tmp/ipc_sock"
#defineQUEUE_LEN 10
int
main(int argc, char *argv[])
{
int serfd, clifd, len, ret;
char rcv_buf[1024];
pid_t pid;
struct sockaddr_un server_addr, client_addr;
if((serfd = socket(AF_UNIX,SOCK_STREAM, 0)) < 0){
perror("Createserver socket error");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family= AF_UNIX;
strncpy(server_addr.sun_path, PATH, sizeof(PATH));
len =offsetof(struct sockaddr_un, sun_path) + strlen(PATH);
unlink(server_addr.sun_path);
if(bind(serfd, (structsockaddr *)&server_addr, len) < 0){
perror("Bindserver socker error");
close(serfd);
unlink(PATH);
exit(EXIT_FAILURE);
}
if(listen(serfd,QUEUE_LEN) < 0){
perror("Listenserver socker error");
close(serfd);
unlink(PATH);
exit(EXIT_FAILURE);
}
len = sizeof(client_addr);
for(;;){
if((clifd = accept(serfd,
(structsockaddr *)&client_addr, &len)) < 0){
perror("Cannot accept client connect request");
continue;
}
pid = fork();
if(pid < 0){
perror("forkerror!");
}else if(pid == 0){
ret = read(clifd, rcv_buf, sizeof(rcv_buf));
if(ret <= 0){
perror("readerror");
}else{
printf("receivedata : %s\n", rcv_buf);
}
}else{
}
}
close(serfd);
close(clifd);
unlink(PATH);
return(0);
}
客户端
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/un.h>
#definePATH "/tmp/ipc_sock"
int
main(int argc, char **argv)
{
int fd, ret, len;
char *send_buf= "hello,world!";
struct sockaddr_un addr;
if((fd = socket(PF_UNIX,SOCK_STREAM, 0)) < 0){
perror("Createsocket error");
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(addr));
addr.sun_family= AF_UNIX;
strncpy(addr.sun_path, PATH, strlen(PATH));
len =offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
if((ret = connect(fd, (structsockaddr *)&addr, len)) < 0){
perror("Cannot connect server");
close(fd);
exit(EXIT_FAILURE);
}
ret = write(fd,send_buf, strlen(send_buf));
if(ret < 0){
printf("writeerror!");
}
close(fd);
return(0);
}