从套接字中迭代read()

时间:2009-04-09 23:03:46

标签: c++ c sockets tcp

这是在套接字上迭代read的正确方法吗?我很难让它正常工作。 data.size也是从套接字填充的unsigned int。它是正确的。 data.dataunsigned char *

if ( data.size > 0 ) {
    data.data = (unsigned char*)malloc(data.size);
    memset(&data.data, 0, data.size);
    int remainingSize = data.size;
    unsigned char *iter = data.data;
    int count = 0;
    do {
        count = read(connect_fd, iter, remainingSize);
        iter += count;
        remainingSize -= count;
    } while (count > 0 && remainingSize > 0);
}
else {
    data.data = 0;
}

提前致谢。

4 个答案:

答案 0 :(得分:9)

在开始将其添加到其他值之前,您需要检查读取的返回值。

当套接字报告EOF时,您将得到零,错误时为-1。请记住,对于套接字EOF与关闭不一样。

答案 1 :(得分:3)

低级套接字编程非常繁琐且容易出错。如果您使用C ++,则应尝试使用更高级别的库,例如BoostACE

我还建议您阅读C++ Network Programming: Mastering Complexity Using ACE and PatternsC++ Network Programming: Systematic Reuse with ACE and Frameworks

答案 2 :(得分:3)

将读取作为while条件的一部分。

while((remainingSize > 0) && (count = read(connect_fd, iter, remainingSize)) > 0)
{
    iter += count;
    remainingSize -= count;
}

这样一旦失败,你就立即停止循环 使用read作为循环条件的一部分是非常常见的模式,否则你需要检查循环内的状态,这会使代码变得更加丑陋。

个人:
我会将整个上面的测试移到一个单独的函数中以便于阅读,但你的milage可能非常。

同样使用malloc(和公司)将导致整个内存管理问题。我会使用std :: vector。当你修改它以开始抛出异常时,这也将证明代码,现在它也将是异常安全的。

因此,假设您将data.data更改为具有std :: vector< unsigned char>的类型。然后

if ( data.size > 0 )
{
    std::vector<unsigned char>   buffer(data.size);

    unsigned char *iter = &buffer[0];
    while(...  read(connect_fd, iter, remainingSize) )
    {
        .....
    }

    ... handle error as required

    buffer.resize(buffer.size() - remainingSize);
    data.data.swap(buffer);
}

答案 3 :(得分:3)

请记住,read()调用是系统调用,因此可能阻塞的来源,即使您使用非阻塞I / O,也是本质上的重量级。我建议尽量减少它们。

在C中使用BSD套接字编程十多年来,一个很好的方法就是使用非阻塞I / O并发出FIONREAD ioctl()来获取等待的总数据量。给定轮询间隔(假设您正在使用某种类型的同步I / O多路复用器,如select()),然后只需读取()所需的数量,以捕获所有这些,然后暂时返回该函数,直到下一个计时器滴答。