【发布时间】: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。