如果POSIX套接字“读取”函数返回0,是否表示发生了错误?
我正在处理遗留代码。此代码调用套接字上的“读取”。如果读取函数返回 0 或更低,调用函数将抛出错误。
n = read(sock, &buff[bytesRead], bytesToRead - bytesRead);
if (n <= 0) {
syslog(LOG_CRIT, "ReadFromSocket: read() failed, errno=%dn", errno);
return FALSE;
}
但是,我注意到这个函数抛出了一个错误,“errno”= 0。
我很好奇我是否遇到读取函数返回 0 的边缘情况,这被错误地解释为错误。
返回值 0 是否表示实际错误?
回答
不,返回值为零并不表示错误。read()的文档说:
成功完成后,这些函数应返回一个非负整数,指示实际读取的字节数。否则,函数应返回 -1 并设置 errno 以指示错误。
也就是说:返回值为零仅意味着实际读取了零个字节。这不是错误。错误由返回值指示-1。errno仍然为零的事实也表明没有发生错误。
至于阻塞/非阻塞部分:
如果fildes [即:第一个参数] 引用一个套接字,则read()应等效于没有设置标志的recv()。
那里说:
如果套接字上没有可用消息,并且套接字的文件描述符上未设置 O_NONBLOCK,则recv()将阻塞,直到消息到达。如果套接字上没有可用消息并且在套接字的文件描述符上设置了 O_NONBLOCK,则recv()将失败并将 errno 设置为 [EAGAIN] 或 [EWOULDBLOCK]。
请记住,该文件是一个套接字,这可以转换为:
- 在阻塞模式下,
read()/recv()调用将等待直到有更多数据可用。因此,返回值为零应表示套接字已关闭,并且不会收到更多数据。可以争论这是否是错误,但它表示有序关闭,因此我不会将其视为错误,而只是“此处没有更多数据可读取,继续!” 反而。 - 在非阻塞模式下,
read()/recv()调用将返回,-1并且errno可以是EAGAIN或EWOULDBLOCK。如果套接字已正确关闭,则在非阻塞模式下,零仍然可以作为返回值出现。
概括:
零并不表示错误。零可以返回,如果:
- 套接字已按顺序关闭,无法接收更多数据(在阻塞和非阻塞模式下),或
- 已收到大小为零的数据报,或
- 通过第三个参数 to 请求了正好零字节
read()。