【问题标题】:How to re-bind local socket after it was closed?本地套接字关闭后如何重新绑定?
【发布时间】:2021-05-03 16:41:21
【问题描述】:

如果一个 unix 套接字绑定到一个路径,listen()s 并做一些工作,之后它被关闭,套接字“文件”保留在文件系统中。但是如果我尝试connect() 到那条路径,我会得到

Connect errno:111
Connection refused

那么“神器”之后还剩下什么?它仍然是文件系统上的inode(我可以用ls 看到它),但它没有绑定,没有监听,我不能cat 它,否则我得到

cat: /tmp/unix.str: No such device or address

那么inode 还剩下什么?我怎样才能让这个“工件”再次活跃、绑定和监听套接字( 不删除它,并使用该路径创建新的套接字)?

  1. “死”的本地套接字的目的是什么(为什么它关闭后不删除,当它不再使用时)?

  2. 我怎样才能恢复“死”的套接字? (主要问题)

  3. 谁负责错误connection refused?不是bind()ed 还是不是listen()ing?

【问题讨论】:

    标签: c linux sockets unix-socket


    【解决方案1】:

    尝试连接时,您会收到“连接被拒绝”,因为该本地套接字上没有任何内容正在侦听。这就像您尝试连接到 TCP 套接字(如果没有在该端口号上侦听)。

    一旦打开套接字的程序关闭,该进程就有责任删除带有unlink 的文件。 man page 声明:

    使用文件名绑定到套接字会在 调用者必须删除的文件系统 不再需要(使用 unlink(2))。通常的 UNIX 紧随其后 语义适用;套接字可以随时取消链接,并将 在最后一次引用时最终从文件系统中删除 关门了。

    如果程序意外崩溃,这当然可能是一个问题,因此您可以通过另外使用锁定文件来解决这个问题。

    另一种选择是使用抽象套接字地址。这是通过将sockaddr_unsun_path 的第一个字节设置为0 并将其余字节设置为指定套接字名称的空终止字符串来完成的。例如:

    struct sockaddr_un sun;
    sun.sun_family = AF_UNIX;
    sun.sun_path[0] = 0;
    strcpy(sun.sunpath + 1, "mysocketname");
    

    这为您提供了一个命名套接字,而文件系统中没有相应的套接字文件。一旦套接字描述符关闭,该套接字将自动消失,因此可以使用该名称打开另一个套接字。

    【讨论】:

    • 我无法重新绑定本地套接字,如果它存在(Bind errno:98; Address already in use),所以我必须首先unlink(),旧(死)套接字,之后我可以重新绑定并再听一遍那条路。但这就是问题,“死”套接字的目的是什么,我如何在没有unlink() 的情况下恢复死套接字(让它再次监听)
    • @milanHrabos 查看我的编辑。它必须是unlink'ed。
    • 那么抽象套接字不是在文件系统上创建为inode 吗?如果不是,如何引用“抽象”(不在文件系统上)?它的数据是如何缓冲的?如果不是普通的inode?​​span>
    • @milanHrabos 文件系统中的套接字描述符不是包含缓冲数据的实际文件。它只是一个指向内核中管理所有这些数据结构的指针。带有抽象地址的套接字是一样的,只是没有对应的外部文件。
    • 创建套接字后(可能通过socket() 函数)然后调用setsockopt() I.E. int enable = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) error("setsockopt(SO_REUSEADDR) failed"); 那么这个socket就可以复用了。 setsockopt
    猜你喜欢
    • 1970-01-01
    • 2019-11-01
    • 2021-05-21
    • 1970-01-01
    • 2011-01-22
    • 2012-05-21
    • 1970-01-01
    • 2016-10-27
    • 2012-10-29
    相关资源
    最近更新 更多