c - 设置了 O_NONBLOCK 的套接字 fd 的多次读取调用失败

标签 c linux sockets select file-descriptor

我正在使用 select()NONBLOCKING 连接 fd 来接受连接并处理输入和输出。我在处理超过缓冲区大小的大数据传输时遇到一些问题。例如这里:

readCount = 1;
while(readCount > 0)
{
    // clear t_input to read new data from the fd
    memset(t_input, 0, CLIENT_INPUT_BUFF_LEN);

    // read data from the client connectionFd and since t_input is 1024 only
    // read that much
    readCount = read(iter->connectionFd, t_input, 1024);
    printf("<<< %d - %s >>> \n", errno, strerror(errno));

    if(readCount == -1)
    {
        if( errno == EAGAIN) 
            break;
    }

    iter->AppendInputData(t_input, readCount);
}

这不适用于大数据。因此,当我传输小于 1024 的数据时,第一个 read 调用成功完成,数据被复制到 AppendInputData 调用中。由于它在一个循环中,第二个 read 调用返回 -1,并将 errno 设置为 EAGAIN 然后中断循环 - 对于这种情况,一切都很好。

但是,在数据大于1024 的情况下,第二次读取调用将再次失败并且errno 设置为EAGAIN。奇怪的是,在 Debug模式下,我没有看到这种行为,第二个或第三个 read 调用返回正常并且收集了所有数据。有人可以解释可能发生的事情吗?

最佳答案

尝试更像这样的东西:

do
{
    // read data from the client connectionFd and since t_input is 1024 only read that much
    readCount = read(iter->connectionFd, t_input, 1024);

    if (readCount == -1)
    {
        if (errno == EAGAIN) 
        {
            fd_set fd;
            FD_ZERO(&fd);
            FD_SET(iter->connectionFd, &fd);

            timeval tv;
            tv.tv_sec = 5;
            tv.tv_usec = 0;

            readCount = select(iter->connectionFd+1, &fd, NULL, NULL, &tv);
            if (readCount == 1)
                continue;

            if (readCount == 0)
            {
                printf("<<< timeout >>> \n");
                break;
            }
        }

        printf("<<< %d - %s >>> \n", errno, strerror(errno));
        break;
    }

    if (readCount == 0)
    {
        printf("<<< disconnect >>> \n");
        break;
    }

    iter->AppendInputData(t_input, readCount);
}
while (true);

关于c - 设置了 O_NONBLOCK 的套接字 fd 的多次读取调用失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25943605/

相关文章:

c 编程输入最后一个元素是@

C传递指针数组

ruby-on-rails - Rails 和 Docker : configure bundler to run bundle install in a docker build for Rails. 4.2.6?

java - 无法连接到远程 JMX 主机

java - 如何在ssh上测试客户端和服务器程序?

c - 通过套接字发送整数和字符

objective-c - 卸载动态库需要两次 dlclose() 调用?

c++ - 从裸数据到 C++ 包装器的类型转换

linux - 错误 ./vpdetection :/gpfs/apps/x86_64-rhel5/matlab/R2012a/sys/os/glnxa64/libstdc++. so.6:找不到版本 `GLIBCXX_3.4.14'

c++ - 为什么我们不关心位顺序?