当使用AF_UNIX
(unix域套接字)时,是否有任何应用程序可以在一个从不调用listen()
的进程中调用bind()
?
在我的系统编程讲座和实验中,我们被要求在一个unix域套接字客户端进程上调用bind()
。是否有任何文档记录的、未文档记录的、或实际的应用程序可以在一个 * 仅限客户端*unix域套接字进程上调用bind?根据我的理解,bind()
创建了一个特殊的套接字文件,这是一个服务器进程将承担的责任。这是正确的吗?
下面是一个示例代码,基于课堂上讨论的概念:
服务器. c
# include <stdio.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/socket.h>
int main() {
int s0, s1;
struct sockaddr sa0 = {AF_UNIX, "a"};
s0 = socket(AF_UNIX, SOCK_STREAM, 0);
bind(s0, &sa0, sizeof(sa0) + sizeof("a"));
listen(s0, 1);
for (;;) {
s1 = accept(s0, NULL, NULL);
puts("connected!");
for (;;) {
char text[1];
ssize_t n = read(s1, &text, sizeof(text));
if (n < 1) {
break;
}
putchar(text[0]);
}
close(s1);
}
close(s0);
unlink("a");
return 0;
}
客户端. c
# include <stdio.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/socket.h>
int main() {
int s0;
struct sockaddr sa0 = {AF_UNIX, "b"};
struct sockaddr sa1 = {AF_UNIX, "a"};
socklen_t sa1_len;
s0 = socket(AF_UNIX, SOCK_STREAM, 0);
bind(s0, &sa0, sizeof(sa0) + sizeof("b")); // What does this do??
connect(s0, &sa1, sizeof(sa1) + sizeof("b"));
for (;;) {
int c = fgetc(stdin);
if (c == EOF) {
break;
}
write(s0, &c, sizeof(c));
}
close(s0);
unlink("b");
return 0;
}
4条答案
按热度按时间8e2ybdfx1#
只有当你需要接收一个
SOCK_STREAM
类型的套接字连接时才需要调用bind()
,但是bind()
的行为取决于SOCKET的域。有一个manual页面专门用于此。有用信息:
地址格式
UNIX域套接字地址以以下结构表示:
在此结构中区分了三种类型的地址:
绑定到一个带有文件名的套接字会在文件系统中创建一个套接字,当调用者不再需要这个套接字时,必须将其删除(使用unlink(2))。套接字可以在任何时候被解除链接,并且当对它的最后引用被关闭时,将最终从文件系统中移除。
因此:
bind()
在客户端中不是必需的。bind()
在您的上下文中为您的套接字命名为"a"
和"b"
bind(s0, &sa0, sizeof(sa0) + sizeof("b"));
和代码中类似行是未定义的行为;它为bind()
提供了错误的大小,该大小超出了&sa0
的界限。正确的代码为bind(s0, &sa0, sizeof sa0);
bind()
在此上下文中(Linux、AF_UNIX)确实创建了一个特殊的套接字文件;如果要删除它,则必须调用unlink()
或remove()
。rjee0c152#
man bind
给出了以下答案:lb3vh1jj3#
在Unix域套接字上调用
bind()
,而不打算调用accept()
,这是一种非常有用的方法,可以确保只有一个进程副本在运行。这比依赖进程名要健壮得多,因为二进制文件可以在另一个名称下复制和运行。然而,异常终止(
SIGSEGV
,作为kill -9 ...
的目标)的清理是一个问题,因为除非应用程序在信号处理程序中删除套接字,否则套接字不会被删除。wfveoks04#
我刚刚在unix数据报套接字上遇到了类似的问题。wpa_supplicant有一个使用unix数据报套接字的控制接口。客户端必须将其套接字的末端绑定到一个路径上,即使它是一个将连接到wpa_supplicant的服务器套接字的客户端套接字。如果不完成这一步,那么服务器将无法向客户端发送回复,尝试失败并返回ENOTCONN错误。
我做C程序员很长时间了,这是我第一次遇到这种行为。看起来wpa_supplicant本质上是试图使用数据报套接字,就好像它们是流套接字一样,我不明白为什么。