linux - connect() 与 unix 域套接字和完整积压

标签 linux macos sockets posix solaris

当 STREAM unix 域套接字的监听积压已满时,connect(2) 在大多数具有 ECONNREFUSED 的系统上失败。它最好返回 EAGAIN。

原因是能够区分死套接字(文件系统中存在节点,但不再有进程监听)和完全积压的两种情况非常有用。我在移植一些 Linux 软件时遇到了这个问题,这些软件有一些代码来清理死套接字,但如果代码可以通过发送垃圾邮件来填充套接字以填充积压来欺骗它们来删除套接字,这就是一个安全漏洞。

只有 Linux 返回 EAGAIN; AIX、Solaris 和 Darwin 遵循 BSD 行为(仅在每个上测试过)。

POSIX 没有将 EAGAIN 列为 connect() (link) 的可能返回码,因此这里可能存在一些合规性问题。

让每个人都改变以适应 Linux 的最佳途径是什么?我可以去 Oracle、Apple 和 FreeBSD PR 提交错误报告,然后在每个组织的邮件列表中解决这个问题。或者我应该在标准机构(奥斯汀集团)中纠缠某人吗?即使优势很明显,尝试让每个人都改变这里是否可取?

最佳答案

无论您是否尝试更改标准,或更改供应商实现 connect() 的方式,我认为从软件的角度来看,都不会产生任何影响。 ECONNREFUSEDEAGAIN 都应被视为重试。

区分这两种情况可能允许您在客户端编写更具体的诊断消息,但重试逻辑应该是相同的。即使监听器当前不存在,它最终也可能存在,因此应该尝试重试。

try_again:
    rc = connect(s, (void *)&addr, sizeof(addr));
    if (rc == 0) return connect_succeeded(s, &addr);
    switch (errno) {
    case EAGAIN:
    case ECONNREFUSED:
        if (should_try_again(retries++)) {
            goto try_again;
        }
        break;
    case EINTR:
        goto try_again;
    default:        
        break;
    }
    return connect_failed(s, errno);

关于linux - connect() 与 unix 域套接字和完整积压,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19221105/

相关文章:

linux - 从套接字写入输出

c++ - 如何判断在哪个.SO库中赋予了C函数?

database - 从 XCode 连接到 Microsoft Access 数据库

linux - 无法导入容器镜像错误 fabric_e_invalid_operation

linux - 防止子字符串中的 Bash 分词

python - 无法从 CLI 或 pyodbc 连接到 Mac 上 docker 容器中运行的 Mssql 服务器 - Azure DS 可以工作吗?

objective-c - OSX 10.10.3 在 dealloc 上使 WebView 崩溃

java - Socket同时读写

linux - 原始套接字与 TUN 设备

c - 如何将数据包从 NF_INET_PRE_ROUTING 移动到 NF_INET_POST_ROUTING?