为什么Sendto()系统调用不返回发送的字节数?

问题描述 投票:0回答:1

在Go的标准库中,网络系统调用Sendto()看起来像这样:

Windows

func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error)

Unix

func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error)

但是,基础系统调用返回所有操作系统(LinuxWindows)上发送的字节数,所以Go为什么只返回错误?

sockets go network-programming system-calls
1个回答
3
投票

它确实应该,但是经常,没有它,您可以逃脱。

我在评论中说,返回值“通常”很重要,但是这可能太过分了。请注意,每个操作系统在这里可能会有细微的差异。我将描述很久以前的传统行为:

  1. sendto在流类型的已连接套接字上(SOCK_STREAMAF_UNIXAF_INET等)基本上与send相同:它循环执行,发送部分数据,直到有些有趣事件发生。有趣的事件包括但不限于这些:

    • 所有数据已发送
    • 信号中断发送
    • 连接被另一端重置

    此时sendto调用返回。如果发送了no数据,则返回值为-1,错误为EINTR;如果发送了一些数据,但不是全部数据,则返回值为短计数。此行为与write系统调用的行为相同。

  2. [sendto在流类型但未连接的套接字上仅以ENOTCONN失败。

  3. [[sendto在连接的数据报套接字上,由于已连接(C0])而报错。

  4. 未连接的数据报套接字上的
  5. EISCONN暂时将其连接(在通话过程中),将消息作为单个数据报发送,并成功并返回发送的长度,或者失败并不发送任何内容并返回-1和[ C0]或其他一些更适当的错误(例如,如果连接失败或目标主机拒绝该数据包或其他错误,尽管并非所有这些错误都可能在所有协议上发生)。

  6. sendto套接字(打包的类似流的实体)上的EMSGSIZE的行为类似于sendto,除了整个消息作为单个数据包发送或完全发送失败。

因此,情况1除外,SOCK_SEQPACKET套接字上的SOCK_STREAM可能会被中断-返回值始终为sendtoSOCK_STREAM。对于情况1,您可以只调用len。在Go的正常使用中,-1的情况永远都不会发生,因为Go运行时会将所有信号定向到进程内的专用OS级线程,这意味着只有在发送一些数据并返回时,您才能获得短暂的回报。然后远程主机突然关闭(并重置)流。即使发生write does,OS EINTR也会产生正确的返回值。

EINTR系统调用更为复杂,因为它允许这么多的标志,并且在不同的系统上具有不同的返回值。 BSD文档说它返回发送的messages的数量,而Linux文档说它返回发送的bytes的数量。各种消息标志也相当依赖于OS。像Go这样的简单包装器并不能真正轻松地隐藏这些差异。 (但是,我仍然看到Go库具有write。)

© www.soinside.com 2019 - 2024. All rights reserved.