74-Unix 域套接字地址结构

1. unix 域协议简介

不同于 ipv4 的 AF_INET,unix 域只用于本机进程间通信,它所使用的完全是另一套协议。在使用 unix 域的时候,socket 函数的第一个参数必须指定为 AF_LOCAL 或者 AF_UNIX,表示创建一个 unix 域套接字。

2. sockaddr_un {}

不同于 ipv4 的 sockaddr_in{} 结构,unix 域的套接字地址结构为 sockaddr_un{},它包含在头文件 sys/un.h 中。


这里写图片描述
图1 sockaddr_un 的定义(linux 3.10 内核)

图 1 中的定义翻译出来就是下面这样:

struct sockaddr_un {   unsigned short int sun_family;   char sun_path[108]; }

算下来,这个结构体一共占用 110 个字节。

不同版本的实现可能稍有不同,比如在 unp 一书中介绍的 sun_path 成员只有 104 字节。POSIX 没有明确定义 sun_path 数组的大小。

sockaddr_un 成员里没有 ip 地址与端口号的概念,它的成员 sun_path 是某个具体的文件路径,该路径必须以'\0' 作为结尾。这种方式称为普通命名。

另一种方式是抽象命名,此时需要让 sun_path[0] = 0. 这个我们后面再说,这里我们先学会普通命名。

3. 示例——构造一个 unix 域套接字地址

构造这样的套接字地址非常简单:

struct sockaddr_un addr; addr.sun_family = AF_UNIX; // 或者让它等于 AF_LOCAL,它们的值是一样的 strncpy(addr.sun_path, "/tmp/dog", sizeof(addr.sun_path) - 1);

注意:unix 域套接字关联的路径应该是一个绝对路径名,而不是相对路径(虽然在某些系统中相对路径能够正常工作,但我们不应该使用它)。POSIX 称给 unix 域套接字相对路径名将导致未定义行为。

4. 绑定 unix 域套接字

程序路径:

git clone https://git.oschina.net/ivan_allen/unp.git

如果你已经 clone 过这个代码了,请使用 git pull 更新一下。本节程序所使用的程序路径是 unp/program/unixdomainprotocols/bindaddr.

4.1 伪代码

int main() {    int sockfd, len;   struct sockaddr_un addr1, addr2;    // 注意第一个参数,必须是 AF_LOCAL 或者 AF_UNIX   sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);    // 如果文件已经存在,删除它   unlink(pathname);                // 创建 unix 域套接字地址   addr1.sun_family = AF_UNIX;    strncpy(addr1.sun_path, "/tmp/dog", sizeof(addr1.sun_path) - 1);      // 绑定套接字地址   bind(sockfd, (struct sockaddr*)&addr1, sizeof(addr1));    // 获取本地套接字地址,保存到 addr2 中   len = sizeof(addr2);   ret = getsockname(sockfd, (struct sockaddr*)&addr2, &len);    printf("bound name = %s, returned len = %d\n", addr2.sun_path, len);    return 0; }

4.2 程序运行结果

unp/program/unixdomainprotocols/bindaddr 路径下,有一个 bindaddr 程序,这是我已经写好的。按照图 2 的方式运行:


这里写图片描述
图2 运行结果

我们看到程序 bindaddr 正常绑定了路径 /tmp/dog,同时生成了一个文件 /tmp/dog,注意观察前面的权限位,以 s 开头,表示这是一个 socket 文件。

5. 总结

  • 掌握创建 unix 套接字
  • 掌握 unix 域套接字地址的创建
  • 掌握 bind unix 套接字地址

说明:本文转自blog.csdn.net,用于学习交流分享,仅代表原文作者观点。如有疑问,请联系我们删除~