76-抽象 unix 域套接字地址

xiaoxiao2021-02-27  239

1. 普通 VS 抽象

前面我们已经学习过了 sockaddr_un 结构,它有一个成员 sun_path,通常它保存的是一个以'\0'为结尾的绝对路径。一旦绑定了一个绝对路径,就会生成一个文件。这种 unix 域套接字地址我们称为普通 unix 域套接字地址。

还有一种 unix 域套接字地址,它的特征是 sun_path[0] 是 null,即 sun_path[0] == '\0'. 这种 unix 域套接字地址称为抽象 unix 域套接字地址。

2. 抽象 unix 域套接字地址

使用这种套接字地址,它并不会在文件系统中产生真正的套接字文件,而是由内核帮我们维护一个抽象套接字文件,它总是以 '@'开头,比如 @dog。所以,它的好处自然很明显,不用产生实际文件了。

既然 sun_path[0] == '\0',使用普通的方法就没办法得知抽象套接字文件的名字。unix 域协议规定使用套接字地址的长度来确定 sun_path.

比如套接字地址内容如下:

struct sockaddr_un addr = { AF_LOCAL, // 长度为 2 {'\0', 'd', 'o', 'g'} // 长度为 4 }

则该 addr 的长度应该设置为 2 + 4 = 6.

在 bind 抽象 unix 域套接字地址的时候,不能再使用 sizeof(addr) 作为 bind 的最后一个参数了,而应该使用上面计算出来的 6 这个结果。

3. unix 域套接字长度计算

在 sys/un.h 有一个宏 SUN_LEN 可以计算该 addr 的长度:

#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))

图1 sys/un.h 中的源码 不过我们不能直接在抽象的 unix 域套接字地址上使用它,因为这个宏使用到了 strlen 函数。使用的时候可以用下面的方法:

struct sockaddr_un addr; addr.sun_family = AF_LOCAL; strcpy(addr.sun_path + 1, "dog"); addr.sun_path[0] = '@'; // 先用非空字符占个位 len = SUN_LEN(&addr); // 计算长度 addr.sun_path[0] = 0; // 设置成抽象 unix 域套接字地址

4. 实验

程序路径:

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

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

4.1 实验步骤

启动服务器 $ ./echo -s --path dog --abstract 启动客户端 $ ./echo --path dog --abstract

4.2 实验结果及分析

图2 左侧是服务器,右侧是客户端

图3 netstat 输出

从图 3 中可以看到,Path 一栏显示的路径是 @dog,而不是 dog. 图 1 中显示的运行结果也很正常。

5. 总结

普通 unix 域套接字地址和抽象 unix 域套接字地址如何创建抽象 unix 域套接字地址
转载请注明原文地址: https://www.6miu.com/read-7205.html

最新回复(0)