在 Linux 中,recv() 有效,但 recvmsg() 无效

Posted

技术标签:

【中文标题】在 Linux 中,recv() 有效,但 recvmsg() 无效【英文标题】:In Linux, recv() works but recvmsg() doesn't 【发布时间】:2019-03-12 14:39:52 【问题描述】:

我在一个函数中得到了这段代码,在树莓派上运行:

struct sockaddr_in addr_buffer;
struct cmsghdr control_buffer;
struct msghdr msghdr;
struct iovec iov[1];
char msg_buffer[1458];

memset(&msg_buffer, 0, sizeof(msg_buffer));
memset(iov, 0, sizeof(iov));
memset(&msghdr, 0, sizeof(msghdr));

iov[0].iov_base = msg_buffer;
iov[0].iov_len = sizeof(msg_buffer);

msg.msg_iov = iov;
msg.msg_iovlen = 1;

msghdr.msg_name = &addr_buffer;
msghdr.msg_namelen = sizeof(addr_buffer);
msghdr.msg_control = &control_buffer;
msghdr.msg_controllen = sizeof(control_buffer);
msghdr.msg_flags = 0;

//int msgsize = recv(udpsocket_fd, &msg_buffer, 4, 0);

int msgs_received = recvmsg(udpsocket_fd, &msghdr, 0);

根据我的阅读,recvmsg() 系统调用应该一次返回到 msghdr 指向的 iovec 一条消息(因为 iovec 数组的长度为 1 个单位)。但是,它不起作用:我正确接收了标头,因为我可以使用调试器读取哪个 IP 发送了数据包,但 msg_buffer 仍然为空。该函数还返回 0,这很奇怪,因为这意味着没有发生错误(将返回 -1),但也意味着没有收到任何消息(尽管标头已更新)

但是,如果我取消注释 recv() 行,一切都会按预期工作,并且消息在 msg_buffer 中。但是,显然,没有收到额外的信息。我已经挠头两个小时了,看不出代码有什么问题。非常感谢您的帮助!

【问题讨论】:

代码缺少一些无法理解的部分。什么是msg(应该是msghdr)?你能做一个简单的可编译的独立示例来说明问题吗? 是的,就是这样。如此愚蠢的错误,但好吧,不会再发生了。谢谢! 【参考方案1】:

从您所显示的内容来看,您只是不正确地初始化了msghdr。尝试在recvmsg 调用之前添加此内容:

mhdr.msg_iov = iov;
mhdr.msg_iovlen = 1;

【讨论】:

谢谢,就是这样! msg 是一个类范围的变量,所以编译器没有给我一个错误,这就是它没有正确写入 iovector 的原因。感谢您的帮助

以上是关于在 Linux 中,recv() 有效,但 recvmsg() 无效的主要内容,如果未能解决你的问题,请参考以下文章

Java从零到企业级电商项目实战

ListBoxListCtrl

是否有可能以某种方式同时在 ZMQ 中使用 Send/Recv(通过多线程)?

Java - UDP通过套接字发送数据..不是rec。所有数据

linux socket阻塞recv怎么返回

linux 下调用recv函数,死循环在recv函数里面,啥原因?