【发布时间】:2022-01-06 12:22:23
【问题描述】:
我遵循了一个关于如何使用 Linux Sockets API 使 Linux 上的两个进程进行通信的教程,这就是它显示的实现它的代码:
连接代码:
char* socket_path = "\0hidden";
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
memset(&addr, 0x0, sizeof(addr));
addr.sun_family = AF_UNIX;
*addr.sun_path = '\0';
strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
connect(fd, (struct sockaddr*)&addr, sizeof(addr));
监听代码:
char* socket_path = "\0hidden";
struct sockaddr_un addr;
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
memset(&addr, 0x0, sizeof(addr));
addr.sun_family = AF_UNIX;
*addr.sun_path = '\0';
strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
bind(fd, (struct sockaddr*)&addr, sizeof(addr));
listen(fd, 5);
基本上,我用 C 为网站编写了一个 Web 服务器,并用 C++ 编写了一个数据库管理系统,并让它们进行通信(在用户的浏览器向我的 Web 服务器发送 HTTP 请求后,它正在使用 AF_INET 进行监听家庭套接字,但这在这里并不重要,只是一些上下文)使用这种机制。数据库系统正在使用它的套接字进行侦听,并且 Web 服务器使用自己的套接字连接到它。它一直运行良好。
但是,我从来不明白套接字路径开头的空字节的目的是什么。比如,"\0hidden" 到底是什么意思,或者它有什么作用?我阅读了有关套接字的联机帮助页,它说明了有关虚拟套接字的一些内容,但它对我来说太技术性了,无法了解正在发生的事情。我对将套接字表示为具有文件描述符的文件的概念也没有清楚的理解。我也不明白strncpy() 的作用。我什至不明白 web 服务器是如何用这个代码块找到数据库系统的,是因为它们的进程都是从同一目录中的可执行文件启动的,还是因为数据库系统是整个系统上唯一监听的进程在 AF_UNIX 套接字上,还是什么?
如果有人能解释一下这个让我困惑了很久的 Linux Sockets API,我将不胜感激。我用谷歌搜索并查看了多个地方,每个人似乎都只是在使用"\0hidden" 而没有解释它,就好像这是每个人都应该知道的一些基本知识。就像,我在这里遗漏了一些理论还是什么?非常感谢任何人提前解释!
【问题讨论】:
-
来自manpage:“通过 sun_path[0] 是空字节这一事实来区分抽象套接字地址(与路径名套接字)”。这意味着路径名不是文件系统中的路径名,而是套接字的抽象名称。
-
抽象套接字地址命名空间也被描述为“不可移植的 Linux 扩展”。
-
"我什至不明白 web 服务器是如何使用这个代码块找到数据库系统的" 两个 sn-ps 中的路径名相同。这就是网络服务器找到数据库服务器的方式。他们必须同意相同的套接字名称。您也可以将其更改为
"\0databaseserver" -
因此操作系统保留了一组内部套接字名称(仅使用这部分 API 的套接字)并且它连接一个套接字到另一个 监听 i> 仅当它们在
bind()和listen()调用中使用的 sockaddr_un 结构的addr.sun_path成员中具有完全相同的条目时才使用套接字,并且它们都以“\0”开头,仅当您确实想使用时这个socket定位方法?