【问题标题】:Socket descriptor becomes invalid, connection remains open套接字描述符无效,连接保持打开状态
【发布时间】:2014-04-26 13:27:45
【问题描述】:

我有两个程序:一个客户端(它只是包装有问题的库)和一个回显服务器。客户端连接回显服务器,发送 X 个字节,回显服务器回显它们。

当客户端尝试从套接字(文件)描述符中读取时,会出现“错误文件描述符”错误(EBADF)。

出于调试目的,在使用 perror() 在控制台上抛出错误之前,我尝试让客户端尝试像另一个问题的答案中建议的那样执行 write(),但问题确实存在。

TL;DR: 套接字描述符没有被修改,客户端最初可以 write() 到套接字,但相同的描述符后来变得无效。为什么?

当前代码可用here(库,第 106 行)、here(可使用库执行)和here(回显服务器,仅从互联网复制粘贴)- 我将添加有用的部分问题的代码在提供答案后立即进行。

【问题讨论】:

  • 您的“错误”处理无效。事物可以将 errno 设置为非零并且不会失败。如果函数返回错误,您应该只检查 errno,您的代码没有正确执行此操作。
  • 这实际上解决了这个问题。我在下一次 read() 时检查了这种问题,但完全忘了在第一次添加检查。谢谢。

标签: c sockets


【解决方案1】:

应该是:

int h;
r = 0;
while (r < 4 && (h = read(client->client_socket, buffer+r, 4 - r)) > 0)
{
    r += h;
}
if (h == -1)
    ...

请注意,将 'errno' 与零进行比较是从不正确的。

【讨论】:

    【解决方案2】:

    正如@Mat 评论的那样,我没有正确检查 read() 是否返回错误: 而不是

    while (r < 4 && errno == 0)
    {
        r += read(client->client_socket, buffer_length, 4 - r);
    }
    

    应该是:

    while (r < 4 && errno == 0)
    {
        int h = read(client->client_socket, buffer_length, 4 - r);
        if (h == -1) { r = -1; break; }
        r += h;
    }
    

    然后在检查错误时:

    if (r == -1)
    {
        switch(errno)
        {
            case EBADF:
                //...
                break;
         }
    }
    

    因为正如他所说,read() 可以改变 errno,即使它成功了。

    【讨论】:

    • 还是错了。你从不应该检查errno,除非函数返回错误(r&lt;0)。
    • 它实际上只在 read() 返回 -1 时检查错误。 errno 检查紧接在 while() 循环之后。
    • 不,这行还是错的:while (r &lt; 4 &amp;&amp; errno == 0)。当r 为0、1、2 或3 时,您不应该检查errno == 0。如果r&lt;0errno==0 无论如何都是不可能的。
    猜你喜欢
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2014-07-04
    • 2011-03-31
    相关资源
    最近更新 更多