如果我有bind()
一个AF_INET
套接字(用于 TCP 连接),那么稍后close()
,下次运行程序时,我可能会遇到问题,因为尽管如此close()
,内核仍然可以拥有与打开的套接字关联的资源。
不过,我对 Unix 域套接字的这个问题不是很清楚。
到目前为止我已经看到了
我需要一个独特的路径来使用它
bind()
。调用时路径必须不存在bind()
,文件将由bind()
. (但是,它在文件系统中可能可见,也可能不可见。如果路径以特殊 char 开头,该文件将不会出现在文件系统中\0
。)如果文件未被
unlink()
-ed,即使在关闭之后,内核也会保留关联的资源,并且套接字将完全正常工作。
问题:
由于无论是close()
还是unlink()
单独都不能使 Unix Domain Socket 消失,那么它们都会可靠地完成这个任务/触发内核放弃与套接字相关的所有资源吗?
reuseaddr
如果同时调用 和 ,close()
我unlink()
是否可能会遇到错误?
编辑(在评论和回答之后):
因此,绑定的 AF_LOCAL 套接字看起来像这样:
unix_domain_socket_inode
-> binded to a socket
-> associated with a file (path)
其unix_domain_socket_inode
寿命将持续到:
- 某些东西使其保持打开状态(套接字未关闭),或者
- 它有关联的路径
如果只有 1. 为真,我们就有一个打开的套接字和一个索引节点,并且一切正常。
如果只有 2. 为真,由于 inode 有一个与之关联的路径,内核无法清理它,但它也不起作用,因为它缺少处理传入连接的套接字资源。它甚至不是一个普通的文件,只是一个繁忙、工作的套接字过去辉煌的死壳。
对于 AF_INET 连接,地址重用问题是为了更好的可用性而设计的选择。
在 AF_LOCAL 的情况下,剩余文件是先前设计选择的产物,这会阻止内核本身在close()
调用时自动清理它在 1 go 中创建的文件。没有关联的隐藏机制,因此内核希望在close()
调用 a 后保留此资源。
答案1
在这种情况下,了解内核具有TIME_WAIT
TCP 连接状态的基本原理非常重要。此状态的目的是允许在同一端口上建立新连接之前,与该连接关联的任何数据包(可能采用更长的路由或以其他方式被延迟)从网络中排出。这样,您可以确保新连接不会收到与旧连接关联的任何数据包。该reuseaddr
选项使开发人员能够传达“不要执行等待”的信息。
Unix 域套接字没有这个问题;reuseaddr
在这种情况下并没有真正意义。
答案2
如果文件没有经过 unlink() 处理,即使在关闭之后,内核也会保留关联的资源,并且套接字将完全正常工作。
不,当最后一个打开套接字的句柄被 close()d 时,内核将释放与套接字关联的所有资源。您只需 unlink() 路径即可再次绑定() 到它。
由于 close() 和 unlink() 都不能单独使 Unix Domain Socket 消失,那么它们都会可靠地完成这个任务/触发内核放弃与套接字关联的所有资源吗?
往上看 ;-)
unix_domain_socket_inode 的生存时间如下:
- 某些东西使其保持打开状态(套接字未关闭),或者
- 它有关联的路径
不对于 2。它的“关联路径”可以被删除(unlink()ed)并且套接字仍然可以通过另一个硬链接访问。
看看我的另一个回答进行演示和解释。
您似乎混淆了套接字 inode(实际套接字 fd 指向的节点,也可以通过 访问/proc/PID/fd/FD
)与它可能绑定到的 inode(类似于 的套接字文件/tmp/.X11-unix/X0
);它们是不同的,后者仅用作“入口点”——一旦绑定到它的套接字关闭,套接字文件就只是文件系统中的虚拟索引节点。
如果路径以特殊字符 \0 开头,则该文件不会出现在文件系统中。)
如果.sun_path
以 开头\0
,它就不再是路径,而是一个“抽象”unix 域地址,与路径不同,它可能包含其他\0
字节并且具有完全不同的语义(任何人都可以连接到套接字,这与旧式 unix 域套接字不同,在旧式 unix 域套接字中连接它受其前导路径确定的文件访问权限的约束)。
请注意,这种“抽象套接字”功能仅存在于 Linux 中。