gpt4 book ai didi

tcp - 完全阻塞套接字 : when,, "send()"是否返回?

转载 作者:可可西里 更新时间:2023-11-01 02:28:49 27 4
gpt4 key购买 nike

BSD 套接字 send() 函数究竟何时返回给调用者?

非阻塞模式下,它应该立即返回,对吗?

至于阻塞模式,man page说:

When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in non-blocking I/O mode.

问题:

  1. 这是否意味着如果内核发送缓冲区中有空间,send() 调用将始终立即返回?
  2. 对于 TCP 和 UDP,send() 调用的行为和性能是否相同?如果不是,为什么不呢?

最佳答案

Does this mean that the send() call will always return immediately if there is room in the kernel send buffer?

是的。只要立即意味着在您提供的内存被复制到内核的缓冲区之后。在某些边缘情况下,这可能不会那么直接。例如,如果您传入的指针触发页面错误,需要从内存映射文件或交换中提取缓冲区,这将显着增加调用返回的延迟。

Is the behavior and performance of the send() call identical for TCP and UDP? If not, why not?

不完全是。可能的性能差异取决于操作系统对 TCP/IP 堆栈的实现。理论上 UDP 套接字可能会稍微便宜一些,因为操作系统需要用它做的事情更少。

编辑:另一方面,由于您可以使用 TCP 在每个系统调用中发送更多数据,通常使用 TCP 每字节的成本可以低很多。这可以通过 sendmmsg() 来缓解在最近的 Linux 内核中。

至于行为,它几乎相同。

对于阻塞套接字,TCP 和 UDP 都会阻塞,直到内核缓冲区中有空间为止。然而,区别在于 UDP 套接字将等待,直到您的整个缓冲区可以存储在内核缓冲区中,而 TCP 套接字可能决定只将单个字节复制到内核缓冲区中(尽管通常它不止一个字节)。

如果您尝试发送大于 64kiB 的数据包,UDP 套接字可能会一直失败并返回 EMSGSIZE。这是因为作为 数据报 套接字的 UDP 保证将整个缓冲区作为单个 IP 数据包(或 IP 数据包片段序列)发送,或者根本不发送。

非阻塞套接字的行为与阻塞版本相同,唯一的异常(exception)是调用失败而不是阻塞(如果内核缓冲区中没有足够的空间),调用失败并返回 EAGAIN(或 EWOULDBLOCK).发生这种情况时,是时候将套接字放回 epoll/kqueue/select(或您正在使用的任何东西)以等待它再次变得可写。

像往常一样,在 POSIX 上工作时,请记住您的调用可能会因 EINTR 而失败(如果调用被信号中断)。在这种情况下,您很可能想再次调用 send()

关于tcp - 完全阻塞套接字 : when,, "send()"是否返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5407182/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com