0

我现在是一段时间的 c 编码器 - 既不是新手也不是专家。现在,我在 PPC Linux 上使用 C 语言有一个特定的守护程序应用程序。我使用 PHP 的 socket_connect 作为客户端在本地连接到该服务。服务器使用 epoll 通过 Unix 套接字多路复用连接。使用 strstr() 解析用户提交的字符串以查找某些字符/单词,如果找到,则同时生成 4 个可连接线程到不同的网站。我使用套接字、连接、写入和读取,通过 TCP 在每个线程的端口 80 上与所述网络服务器进行交互。所有连接和写入似乎都是成功的。然而,对网络服务器套接字的读取失败,其中一个 (A) 所有 3 个线程似乎都挂起,只有一个线程返回 -1 并且 errno 设置为 104。响应线程需要大约 10 分钟 - 一个永恒的时间:-(。*我在某处读到 104(是 EINTR?),在网络上下文中表明...'连接已被对等方重置';或 (B) 来自 3 个线程的 0 个字节,并且 4 个线程中只有 1 个实际上返回了一些数据。套接字不是读/写线程安全的吗?我使用线程安全(和可重入)的 libc 函数,例如 strtok_r、gethostbyname_r 等。

*我怀疑上述虚拟主机实际上是在重置连接,因为当我运行单线程独立(其他一切都相同)时,所有事情都完美无缺,但当然是串联而不是并行。

还有第二个问题(哎呀),我无法回信给连接到我的 epoll-ed Unix 套接字的客户端。我的守护程序应用程序将永远挂起并占用 CPU > 100%。然而,没有任何东西写给客户端。确定客户端(一个非常典型的 PHP 套接字应用程序)在发生这种情况时没有关闭连接 - 也没有检测到错误。有任何想法吗?

即使使用 Valgrind、GDB 或大量日志记录,我也无法弄清楚有什么问题。请在力所能及的地方提供帮助。

4

2 回答 2

0

是的,读/写是线程安全的。但是,如果您使用它们,请注意 gethostbyname() 和 getservbyname() - 它们返回指向静态数据的指针,并且可能不是线程安全的。

errno 104 是 ECONNREFUSED(不是 EINTR)。使用 strerror 或 perror 获取特定 errno 代码的文本错误消息(如“对等连接重置”)。

找出问题所在的最佳方法通常是进行非常详细的日志记录——记录每个操作的结果,以及连接到的 IP 地址/端口、读/写字节数、线程 ID 等详细信息. 而且,当然,请确保您的日志记录代码是线程安全的 :-)

于 2010-04-06T04:58:21.883 回答
0

10 分钟后获得 ECONNRESET 听起来像是连接超时的结果。Web 服务器未发送数据或您的应用程序未接收数据。

要测试前者,请将 Wireshark 之类的程序连接到本地环回设备,并查找进出您正在使用的端口的流量。

对于后面的内容,请查看 epoll() 手册页。他们提到了使用边缘触发事件可能导致锁定的场景,因为缓冲区中仍有数据,但没有新数据进入,因此不会触发新事件。

于 2010-04-26T23:05:04.203 回答