我正在使用write
(man 2 write)将数据写入具有已建立,阻塞且非常慢的TCP连接的套接字。我正在写大块的数据。 write
返回写入的实际大小,当然发生并非所有数据都是由于(可能)超出此问题范围的原因而写入的。
为了确保我将写入调用封装在这样的小循环中:
do {
ssize_t ret = write(client, p, count);
if (ret <= 0)
break;
p += ret;
count -= ret;
} while (count);
if (count != 0)
return -ENODEV;
有没有更好的方法,比如在文件描述符上设置一个标志,从而让低层处理它?</ p>
答案 0 :(得分:6)
我建议使用while
循环而不是do {} while
来为案例count == 0
提供一致的行为。此外,一些失败的案例不是错误:
while (count > 0) {
ssize_t ret = write(client, p, count);
if (ret <= 0) {
if (ret == 0)
return -ENODEV;
if (errno == EINTR)
continue;
else
return -errno;
}
p += ret;
count -= ret;
}
如果在写入任何数据之前系统调用被EINTR
中断,则设置 signal
。在这种情况下应该重新启动write
。如果client
句柄设置为非阻止,您还应该处理EAGAIN
和EWOULDBLOCK
。
来自wildplasser的答案的更紧凑和优雅的版本:
for (size_t done = 0; done < count; ) {
ssize_t ret = write(client, p + done, count - done);
if (ret == 0) return -ENODEV;
if (ret < 0 && errno != EINTR) return -errno;
done += ret;
}
答案 1 :(得分:1)
size_t done;
ssize_t ret;
for (done = 0; done < size; done += ret) {
ret = write(client, buff + done, size-done);
if (ret == 0) return -ENODEV;
if (ret == -1 && errno == EINTR) { ret = 0; continue; }
if (ret == -1) return -errno;
}