【问题标题】:Select and read sockets (Unix)选择和读取套接字 (Unix)
【发布时间】:2011-08-30 00:30:42
【问题描述】:

我在 Unix 上基于 telnet 的服务器出现间歇性问题(该问题在 AIX 和 Linux 上都出现)。 服务器打开两个套接字,一个用于客户端 telnet 会话,一个用于与服务器在同一台机器上运行的程序。这个想法是数据通过服务器传入和传出这个程序。

当前设置有一个循环,使用 select 等待“读取”文件描述符变为可用,然后使用 select 等待“写入”文件描述符变为可用。

然后程序从传入的文件描述符中读取,然后在写入传出描述符之前处理数据。

下面的 sn-p 显示了正在发生的事情。问题是读取失败的情况非常偶然,因为 errno 被设置为 ECONNRESET 或 ETIMEDOUT。这些都不是 read 记录的代码,那么它们来自哪里?

真正的问题是,我怎样才能阻止这种情况发生,或者优雅地处理它? 连续进行两次选择会是问题吗?

目前的处理行为是关机重启。需要注意的一点是,一旦发生这种情况,通常会发生三到四次,然后就会消失。系统负载似乎并不那么高(它是一台大型服务器)。

        if (select(8, &readset, NULL, NULL, NULL) < 0)
                {
                break;
                }
        if (select(8, NULL, &writeset, NULL, NULL) < 0)
                {
                break;
                }

        if (FD_ISSET(STDIN_FILENO, &readset)
        && FD_ISSET(fdout, &writeset))
                {
                if ((nread = read(STDIN_FILENO, buff, BUFFSIZE)) < 0)
                        {
                        /* This sometimes fails with errno = 
                           ECONNRESET or ETIMEDOUT */
                        break;
                        }
                }

【问题讨论】:

  • 您知道,您可以将这两个select 调用合二为一。另外,select 的第一个参数应该是集合中的最大 fd + 1,而不是 8。另外,stdin 是套接字吗?
  • STDIN_FILENO 返回 ETIMEDOUT 是不寻常的。你有什么特别的吗? (重定向、fcntls 等)?
  • 我建议你从执行 Hasturkun 的两个建议开始,如果处理不当,select 可能会非常脾气暴躁。
  • 当只有一个 fd 准备好时,我认为将它们都放入一个选择中可能会返回,我是否正确? IE。写入可能不会与读取同时准备好。
  • 另外,在这种情况下 8 很好 - 我知道这种风格很糟糕,但这不是我的代码。这两个 fd 分别是 4 和 5。

标签: sockets unix


【解决方案1】:

查看第 85 行和第 98 行 http://lxr.free-electrons.com/source/arch/mips/include/asm/errno.h 中的 cmets:这些基本上表示网络连接重置或超时。检查并查看您是否可以在远程网络程序上调整超时,或发送一些定期填充字节以确保连接始终保持唤醒状态。您可能只是远程客户端和本地服务器之间的网络传输路径错误的受害者(当我的 DSL 线路打嗝时,我会遇到这种情况)。

编辑:不确定反对票的用途。 man page for read 明确表示:

可能会出现其他错误,具体取决于连接到 fd 的对象。

错误可能发生在select,而不是read:您没有在select 之后检查错误,您只是继续到read,如果@ 将失败987654327@ 返回错误。我敢打赌,如果您在 select 调用后检查 errno 值,您会看到错误:您无需等待 read 看到错误。

【讨论】:

  • 您的编辑可能会得到另一个-1,回复:错误来自哪里。失败的read 将覆盖errno
  • 我有理由确定这不是“真正的”超时,因为它会在连接时立即发生。
  • 第 7 节的各个手册页记录了读取(和其他系统调用)可以在不同类型的套接字上返回的附加错误代码。参见socket(7)ip(7)tcp(7) 和/或unix(7)。请注意,选择调用通常不会给您错误代码;它将返回成功,这意味着对套接字的读取不会阻塞
猜你喜欢
  • 2011-12-27
  • 2017-09-30
  • 1970-01-01
  • 1970-01-01
  • 2015-05-09
  • 2019-02-23
  • 2023-03-05
  • 1970-01-01
  • 2012-02-08
相关资源
最近更新 更多