6

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

在初始化所需的结构(如在 iovec 和 msghdr 中)并成功将客户端连接到服务器后,我的 sendmsg() 调用失败并出现“没有可用的缓冲区空间”错误。

这是 linux man 报告的有关此类错误的内容:

网络接口的输出队列已满。这一般表示接口已经停止发送,但可能是暂时拥塞造成的。(通常,这在 Linux 中不会发生。当设备队列溢出时,数据包会被静默丢弃。)

我在互联网上四处寻找,结果发现 sendmsg() 没有被广泛使用,没有人能与这种类型的错误联系起来。我发现的唯一有用的建议是检查可能过多的打开套接字,但我总是关闭我创建的每个套接字。

所以我被困住了,基本上是因为我是个菜鸟,我不知道该去哪里解决这类问题。

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

这是迄今为止我在 pastebin 上编写的代码:客户端服务器

- 解决了 -

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

4

3 回答 3

4

正如其他人指出的那样, 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");
于 2012-10-10T14:16:47.180 回答
3

msg_iovlen字段包含iov数组中元素的数量,而不是其大小(以字节为单位)。

系统将以下未初始化的内存解释为iov元素,最终得到的数据包大于可用的套接字缓冲区空间,因此拒绝发送数据。

于 2012-10-10T14:11:25.943 回答
2

好的,所以在你的代码中我发现了这个:

mh.msg_iovlen = sizeof(iov);

它将msg_iovlen成员设置为struct iovec. 但是文档说明了这个领域:

size_t msg_iovlen; /* # msg_iov 中的元素 */

所以你的代码是错误的,它告诉sendmsg()它发送的元素比你实际初始化的要多。

于 2012-10-10T14:13:25.653 回答