我不是C编程方面的专家,但我正在尝试使用sendmsg()和recvmsg()编写一个相当简单的程序,在客户端和服务器之间发送消息(两者都在同一台机器上,所以基本上我正在向localhost发送消息。)
在初始化所需的结构(如在iovec和msghdr中)并成功将客户端连接到服务器之后,我的sendmsg()调用失败并显示“no buffer space avaliable”errno。
这是linux man报告的这类错误:
网络接口的输出队列已满。这通常表示接口已停止发送,但可能是由瞬态拥塞引起的。 (通常情况下,Linux中不会发生这种情况。当设备队列溢出时,只会静默丢弃数据包。)
我环顾四周,因此我发现sendmsg()没有被广泛使用,没有人能与这种类型的错误联系起来。我找到的唯一有用的建议是检查可能多余的开放套接字,但我再次关闭我创建的每个套接字。
所以我被卡住了,主要是因为我很不知道在哪里找到解决这类问题的确切位置。
如果有人知道如何继续,那就太好了。 (请不要告诉我不要使用sendmsg(),因为我的工作的全部目的是理解这个系统调用,而不是向自己发送消息)
以下是我到目前为止在pastebin上编写的代码:client和server
- 解决 -
非常感谢你。我已经能够解决这个问题,并修复了我所犯的其他错误,所以这里是sendmsg()和recvmsg()工作消息传递的功能代码:Client和Server
答案 0 :(得分:3)
msg_iovlen
字段包含 iov 数组中的元素数,而不是字节数。
系统将以下未初始化的内存解释为 iov 元素,最终得到的数据包大于可用的套接字缓冲区空间,因此拒绝发送数据。
答案 1 :(得分:2)
好的,所以在你的代码中我发现了这个:
mh.msg_iovlen = sizeof(iov);
将msg_iovlen
成员设置为struct iovec
的大小。但文档说明了这个领域:
size_t msg_iovlen; msg_iov * /
中的/ *#个元素
所以你的代码错了,它告诉sendmsg()
它会发送比实际初始化更多的元素。
答案 2 :(得分:2)
正如其他人所指出的那样,iovlen应该是1.但是,你想在初始化一些字段之前将mh归零,因为你可能在未初始化的字段中发送垃圾并且系统调用变得混乱。此外,设置msg_name和msg_namelen并没有任何意义,因为你已连接,无论如何都无法改变你对数据发送位置的看法。
这对我的客户端代码有用:
/* The message header contains parameters for sendmsg. */
memset(&mh, 0, sizeof(mh));
mh.msg_iov = iov;
mh.msg_iovlen = 1;
printf("mh structure initialized \n");