- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在编写一个程序,使用 sendmsg
在两个进程之间传递文件描述符和 recvmsg
通过域套接字。对于发送文件描述符,附加数据包含在 msghdr.msg_iov
中和 msghdr.msg_iolen
.然而,我被告知类似于正常read
和 write
系统调用,sendmsg
和 recvmsg
也有部分读/写问题。在这种情况下,是否会为每个部分数据自动复制辅助字段中的数据?我问这个是因为我的实现需要非阻塞机制。让我用下面的例子来详细说明一下
发件人:发送msghdr
包含 fd
的数据在辅助领域和K
msg_iov
中的字节数
接收方:(1) 部分读取,K1
字节 (2) 部分读取,K-K1
字节
现在如上面的例子,我实际上应该在所有数据到达时处理步骤(2)之后的数据。在这种情况下,我还能正确提取 fd
吗?来自辅助领域?还是只出现在第一次部分阅读中?
最佳答案
通过快速查看内核源代码(linux,但见下文),我相信由您来确保辅助数据只发送一次。也就是说,在非阻塞模式下,如果接收套接字中没有空间,您将返回EAGAIN
/EWOULDBLOCK
,并且不会发送数据和辅助数据。但是如果接收方有一些空间,那么数据的初始部分将被发送,辅助数据也将被发送。然后您会收到一个返回字节数,指示已部分发送,但辅助数据已发送。
当您尝试发送消息的其余部分时,您需要注意这一点,因为内核不会维护您之前发送的部分缓冲区的内存,后续缓冲区在逻辑上是连续的(真的不可能——你可能会发送完全不同的数据)。因此,如果您只是为后续缓冲区部分提供相同的辅助数据,我相信内核会很乐意为您的后续缓冲区部分再次提供辅助数据。这可能会导致接收方出现重复的文件描述符(如果您不避免的话,您可能会忽略关闭它们)。
现在,如果您在发送方处于阻塞模式,并且传输被分成多个部分,则辅助数据将仅发送一次 - 第一个缓冲区部分,因为整个缓冲区的发送仍在内核控制。
因此,在接收端,如果您没有收到完整的逻辑消息,您需要注意辅助数据伴随着接收到的数据的第一 block 。
我相信此行为与@Klas-Lindbäck ( https://unix.stackexchange.com/questions/185011/what-happens-with-unix-stream-ancillary-data-on-partial-reads) 给出的 stackexchange 引用中报告的行为一致。 (虽然这个问题没有涉及非阻塞模式。)
这个答案是特定于 linux 的。因此,在其他操作系统上的结果当然可能会略有不同,尽管我很难看出它们有何显着差异并仍然保持理智的语义。内核无法合理地维护之前发送的内容的内存,并且 sendmsg
原型(prototype)不允许它覆盖用户的 msghdr
以反射(reflect) msg_control
部分已经发送。
关于c - sendmsg/recvmsg 中的部分读/写问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38431713/
我正在尝试在 Linux 中实现自己的传输层协议(protocol)以进行实验。我将使用套接字接口(interface)并使用 sock_register 添加我的协议(protocol)。对于 pr
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎偏离主题,因为它缺乏足够的信息来诊断问题。 更详细地描述您的问题或 include a mini
我想知道内核如何使用这个 sendmsg() 函数填充 ip header 。 sendmsg() 函数用于在较少的连接中发送消息通过套接字。我们向该函数传递 3 个参数。它们是,文件描述符,msgh
首先是一些上下文:有一个主程序(一个网络服务器),它派生了一堆工作人员,并等待传入的连接。当它接受一个时,它通过 sendmsg() 原语将套接字描述符发送给其中一个工作人员。 这是应该发送描述符
我不是 C 编程专家,但我正在尝试使用 sendmsg() 和 recvmsg() 编写一个相当简单的程序来在客户端和服务器(两者都在同一台机器上,所以基本上我是在向本地主机发送消息)。 在初始化所需
如您所知,sendmsg 有这样的声明: int sendmsg(int s, const struct msghdr *msg, int flags); 和msghdr结构有这种形式: struct
sendmsg() 允许将辅助数据发送到另一个套接字,我想知道它是如何工作的。 1) 辅助数据是否与正常消息一起打包? 2) 如果是这样,远程接收套接字如何知道如何解析它? 3) 远程接收客户端如何检
我正在将项目从 Delphi 2006 升级到 Delphi XE2,并且遇到了编译错误没有可以使用这些参数调用的“SendMsg”的重载版本。这是问题所在的代码。 procedure TMessag
我使用linux 3.x和现代glibc(2.19)。 我想发送几个以太网帧,而无需从内核/用户空间来回切换。 我有MTU = 1500,我想发送800 KB。 我这样初始化接收者地址: struct
我正在使用 unix 域套接字在不同进程之间发送打开的文件描述符。 Unix 域套接字工作正常,但是当我使用 sendmsg 发送文件描述符时,发生了一些奇怪的事情。该函数在 sendmsg 之后返回
我正在编写一个程序,使用 sendmsg 在两个进程之间传递文件描述符和 recvmsg通过域套接字。对于发送文件描述符,附加数据包含在 msghdr.msg_iov 中和 msghdr.msg_io
在 Linux 中运行 ldapsearch 实用程序时,“sendmsg”函数失败并出现错误代码 9。错误代码 9 代表什么?手册页未提供有关错误代码的信息。 最佳答案 您可以在此页面中找到所有错误
在 IPv4 的情况下,我看到 sendmsg 有以下行为: 假设10.1.2.3是客户端IP。10.1.2.10配置在客户端的其中一个接口(interface)上。 在UDP报文中,在数据包中加入如
我正在尝试使用 C 通过 sendmsg 发送原始以太网数据包。此代码成功打开原始数据包套接字,尝试用单个字节数组 (char message[]) 填充 struct iovec,然后用目标地址、地
我拥有的是进程 ID 和来自该进程的文件描述符。除了 sendmsg 之外,还有什么方法可以复制(或重新打开)该进程的文件描述符以供 Linux 中的另一个进程使用? Windows 有用于此目的的
如果为 in_pktinfo.ipi_ifindex 设置了值,则使用 sendmsg() 可以指定从哪个接口(interface)发送数据报。 如果数据包是对使用 recvmsg() 接收到的数据报
我建立了一个简单的客户端和服务器程序,使用 TCP 套接字进行通信。服务器等待客户端连接,并回复是否收到客户端的消息。以下是代码在服务器和客户端中的实现方式: 服务端代码: listen(sockf
我使用 cmsg 在 linux socket tx 上激活时间戳。 ssize_t sendWithOptions (int sd, std::vector &payload, uint32_t d
我在 UDP 套接字编程中遇到了一些问题。我想使用 sendmsg() 和 recvmsg() API 以便能够在客户端和服务器之间进行通信。客户端代码返回错误号 105 {ENOBUFS}。我不知道
我正在编写自己的 DNS 黑洞来阻止我家庭网络上的广告和恶意软件。我意识到这种类型的程序已经存在,但我想学习这个过程并编写自己的程序。从 Linux 文档来看,似乎可以告诉 sendmsg() 使用不
我是一名优秀的程序员,十分优秀!