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