如您所知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 */
};
Run Code Online (Sandbox Code Playgroud)
如你所见,msghdr有一个缓冲区数组,iovec并且缓冲区数为msg_iovlen.我想知道sendmsg如何发送这些缓冲区.它是连接所有缓冲区并发送还是以for循环发送?
Sté*_*hen 26
该联机帮助页提到了一条消息(单数)和多个元素(复数):
对于
send()和sendto(),消息在,buf并且有长度len.因为sendmsg(),数组的元素指向消息msg.msg_iov.该sendmsg()调用还允许发送辅助数据(也称为控制信息).
对于流套接字,无论哪种方式都无关紧要.您发送的任何数据最终都会在另一侧作为一个长数据流结束.
对于数据报或消息套接字,我可以看到为什么更清晰一点会有所帮助.但是看起来你只用一个sndmsg电话发送一个数据报或消息; 每个缓冲元素不是一个.
我实际上是出于好奇而挖掘了Linux源代码,并对这个答案有了更好的认识.看起来send,它sendto只是sendmsgLinux中的包装器,可以struct msghdr为您构建.事实上,UDP sendmsg实现为每个呼叫提供了一个 UDP标头的空间sendmsg.
如果表现是你所担心的,那么sendmsg如果你只传入一个表演,你看起来并不会受益iovec.但是,如果你在用户空间中连接缓冲区,这可能会赢得一些.
它有点类似writev,有一个额外的好处,你可以指定一个目标地址用于无连接套接字,如UDP.如果您正在进行此类操作,还可以添加辅助数据.(通常用于跨UNIX域套接字发送文件描述符.)