这是在套接字上迭代read
的正确方法吗?我很难让它正常工作。 data.size
也是从套接字填充的unsigned int
。它是正确的。 data.data
是unsigned 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;
}
提前致谢。
答案 0 :(得分:9)
在开始将其添加到其他值之前,您需要检查读取的返回值。
当套接字报告EOF时,您将得到零,错误时为-1。请记住,对于套接字EOF与关闭不一样。
答案 1 :(得分:3)
低级套接字编程非常繁琐且容易出错。如果您使用C ++,则应尝试使用更高级别的库,例如Boost或ACE。
我还建议您阅读C++ Network Programming: Mastering Complexity Using ACE and Patterns和C++ 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()),然后只需读取()所需的数量,以捕获所有这些,然后暂时返回该函数,直到下一个计时器滴答。