在网络上进行通信的时候,我们一般会使用socket
进行通信,实际上socket
也可以用于同一台主机上的两个进程间的通信,称为本地套接字。本地套接字具有如下的优势:
-
UNIX
域套接字仅仅复制数据,不执行协议处理,不需要添加或删除网络报头,无需计算校验和。 -
UNIX
域数据报服务是可靠的,不会丢失也不会传递出错。
UNIX
套接字的地址有struct sockaddr_un
结构体表示。
#include <sys/un.h>
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
sun_path
成员包含一个路径,当将一个地址绑定到一个UNIX
套接字上,系统会用该路径创建一个S_IFSOCK
类型的文件。
如果我们绑定一个已经存在的文件,bind
会出错。当程序退出时,也并不会删除这个文件,所以在程序退出前需要对文件解除关联。
int fd;
int size;
struct sockaddr_un addr;
//unlink("./hello");
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "./hello");
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket\n");
return -1;
}
size = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
if (bind(fd, (struct sockaddr *)&addr, size) < 0) {
close(fd);
perror("bind\n");
}
close(fd);
如上图所示,执行bind
之后会生成一个S_IFSOCK
类型的文件。第二次执行的时候,由于该文件存在,会导致bind
失败。
扩展:
#define <stddef.h>
#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
计算成员MEMBER
在结构体类型TYPE
中的偏移量,巧妙使用0地址的特点。
+-----------+
| |
| |
| |
| |
| |
MEMBER +-----------+ +++
| | ^
| | |
| | +
| | offsetof
| | +
| | ^
TYPE 0 +-----------+ +++
了解了unix
套接字的时候之后,我们就可以使用其实现服务端、客户端的通信。
server:
struct sockaddr_un un;
fd = socket();
bind();
listen()
accept()
client:
struct sockaddr_un un;
//绑定server端创建的sun_path
fd = socket();
connect();
write();