POSIX 部分写入()

Lv *_*eng 6 c sockets linux posix

如在SUSv4描述或POSIX.1-2008
http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#tag_16_685_08
写()调用可以比返回一个值以下为nbytes如果()坏到一个非阻塞管道/FIFO。因此,有必要检查返回值并在下面演示的循环中写入() 缓冲区的其余部分:

while (bytes_to_write > 0) {
    select(...);                 // Or poll()
    retv = write(...);
    if (retv < 0)
        ...                      // Error
    bytes_to_write -= retv;
}
Run Code Online (Sandbox Code Playgroud)

该标准没有提及常规文件、特殊文件(又名设备)和套接字,尤其是基于流的套接字(例如 TCP 套接字和 UNIX 域套接字)。

那么,我有以下两个问题:

  • 部分写入()(或部分发送())是否可能发生在常规文件(或未设置O_NONBLOCK 的套接字)上?
  • 如何writev可以获得()和SENDMSG()上NONBLOCK插座?这很重要,因为处理部分写入的向量(struct iovec [])有点麻烦。

对不起,英语蹩脚。

Lv *_*eng 5

好的。由于标准不提供任何保证,我们不能假设完全write()s。

我在 Google 上搜索了部分 write v并得到了答案:

http://developerweb.net/viewtopic.php?id=4154

是的,我以前也见过这种行为(尽管使用 sendmsg() 和它的 iovecs)...而且,实际上,这不是不正确/意外的行为... read()/recv() 和 write( )/send()(以及 I/O 函数的所有排列)可以返回短读/写,并且所有套接字代码都需要准备好处理这个......它们是阻塞还是非阻塞并不重要-阻塞模式套接字,或者......所有控制的是当缓冲区完全空(在输入的情况下)或完全满(在输出的情况下)时发生的事情......但是,当发送缓冲区不是相当满,任何超过剩余可用空间量的写入(通过阻塞或非阻塞套接字)都会尽可能多地写入,然后返回短写入计数......而且,你应该处理再次调用它,发送剩余金额...使用普通的 write()/send(),很容易做到,但是使用 writev()/sendmsg() iovecs,它确实变得难以处理,并且真的很痛苦......但是,你仍然必须这样做

writev_all() 无法避免。

谢谢。


use*_*421 -1

常规文件上是否可能发生部分 write()(或部分 send())

是的。

(或未设置 O_NONBLOCK 的套接字)?

是的。

NONBLOCK 套接字上的 writev() 和 sendmsg() 怎么样?

是的。

这非常重要,因为处理部分写入的向量(struct iovec [])有点麻烦。

并不真地。您知道写入了多少字节,只需向前移动指针并相应地减少大小即可。如果这对你来说太麻烦,请使用阻塞模式。