如您所知 sendmsg 具有以下声明:
int sendmsg(int s, const struct msghdr *msg, int flags);
msghdr 结构具有以下形式:

struct msghdr {
    void         * msg_name;     /* optional address */
    socklen_t    msg_namelen;    /* size of address */
    struct iovec * msg_iov;      /* scatter/gather array */
    size_t       msg_iovlen;     /* # elements in msg_iov */
    void         * msg_control;  /* ancillary data, see below */
    socklen_t    msg_controllen; /* ancillary data buffer len */
    int          msg_flags;      /* flags on received message */
};

如您所见,msghdr具有一个数组iovec缓冲区,并且缓冲区计数为msg_iovlen。我想知道的是sendmsg如何发送这些缓冲区。它是连接所有缓冲区并发送还是在for循环中发送?

最佳答案

手册页提到了一条消息(单数)和多个元素(复数):



对于流套接字,无论哪种方式都没有关系。您发送的任何数据都将最终成为另一端的一长串数据流。

对于数据报或消息套接字,我可以理解为什么再进行一些澄清会有所帮助。但是似乎您只通过一个sndmsg调用就发送了一个数据报或消息。每个缓冲区元素一个。

出于好奇,我实际上是在研究Linux源代码,以便对这个答案有更好的了解。看起来sendsendto只是Linux中sendmsg的包装器,它们为您构建了struct msghdr。实际上,UDP sendmsg实现为每个sendmsg调用留出一个UDP header 的空间。

如果您担心性能,那么仅传递一个sendmsg似乎就不会从iovec中受益。但是,如果您要在用户空间中串联缓冲区,则可能会为您赢得一些机会。

它有点类似于writev,其附加好处是您可以指定用于无连接套接字(如UDP)的目标地址。如果您喜欢这种事情,还可以添加辅助数据。 (通常用于在UNIX域套接字之间发送文件描述符。)

10-06 02:36