在网络上进行通信的时候,我们一般会使用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 +-----------+ +++
ascii换图工具
了解了unix
套接字的时候之后,我们就可以使用其实现服务端、客户端的通信。
server:
struct sockaddr_un un; fd = socket(); bind(); listen() accept()
client:
struct sockaddr_un un; //绑定server端创建的sun_path fd = socket(); connect(); write();