C sendmsg()没有可用的缓冲区空间

时间:2012-10-10 13:15:29

标签: c

我不是C编程方面的专家,但我正在尝试使用sendmsg()和recvmsg()编写一个相当简单的程序,在客户端和服务器之间发送消息(两者都在同一台机器上,所以基本上我正在向localhost发送消息。)

在初始化所需的结构(如在iovec和msghdr中)并成功将客户端连接到服务器之后,我的sendmsg()调用失败并显示“no buffer space avaliable”errno。

这是linux man报告的这类错误:

  

网络接口的输出队列已满。这通常表示接口已停止发送,但可能是由瞬态拥塞引起的。 (通常情况下,Linux中不会发生这种情况。当设备队列溢出时,只会静默丢弃数据包。)

我环顾四周,因此我发现sendmsg()没有被广泛使用,没有人能与这种类型的错误联系起来。我找到的唯一有用的建议是检查可能多余的开放套接字,但我再次关闭我创建的每个套接字。

所以我被卡住了,主要是因为我很不知道在哪里找到解决这类问题的确切位置。

如果有人知道如何继续,那就太好了。 (请不要告诉我不要使用sendmsg(),因为我的工作的全部目的是理解这个系统调用,而不是向自己发送消息)

以下是我到目前为止在pastebin上编写的代码:clientserver

- 解决 -

非常感谢你。我已经能够解决这个问题,并修复了我所犯的其他错误,所以这里是sendmsg()和recvmsg()工作消息传递的功能代码:ClientServer

3 个答案:

答案 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");