在Go的标准库中,网络系统调用Sendto()
如下所示:
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)
答案 0 :(得分:3)
它确实应该-但通常,您可以在没有它的情况下逃脱。
我在评论中说,返回值“通常”很重要,但是这可能太过分了。请注意,每个操作系统在这里可能会有细微的差异。我将描述很久以前的传统行为:
sendto
或SOCK_STREAM
等的AF_UNIX
上的 AF_INET
与send
基本上相同:它循环,发送部分数据,直到发生一些有趣的事件。有趣的事件包括但不限于这些:
此时sendto
调用返回。如果没有发送数据,则返回值为-1
,错误为EINTR
,如果没有发送所有数据,则返回值为短计数。此行为与write
系统调用的行为相同。
sendto
在流类型但未连接的套接字上以ENOTCONN
失败。
sendto
上已连接的数据报套接字错误,并抱怨已连接(EISCONN
)。
sendto
暂时将其连接(在通话期间),将消息作为单个数据报发送,并成功并返回发送的长度,或者失败并什么都不发送并返回-1和EMSGSIZE
或其他一些更适当的错误(例如,如果连接失败或目标主机拒绝该数据包等,尽管并非所有这些错误都可能在所有协议上发生)。
sendto
套接字上的 SOCK_SEQPACKET
(类似于流的打包实体)的行为类似于SOCK_STREAM
,除了整个消息作为单个数据包发送或发送完全失败。
因此,除了情况1 — sendto
套接字上的SOCK_STREAM
可能会中断之外,返回值始终为len
或-1
。对于情况1,您可以只调用write
。 EINTR
这种情况永远不要在Go中正常使用,因为Go运行时会将所有信号定向到进程内的专用OS级线程,这意味着只有获得一些数据时,您才能获得短暂的回报。发送,然后远程主机突然关闭(并重置)流。即使发生EINTR
,操作系统write
也会产生正确的返回值。
sendmsg
系统调用更为复杂,因为它允许这么多的标志,并且在不同的系统上具有不同的返回值。 BSD文档说它返回发送的消息数量,而Linux文档说它返回发送的 bytes 数量。各种消息标志也相当依赖于OS。像Go这样的简单包装器并不能真正轻松地隐藏这些差异。 (但是,我仍然看到Go库中有SendmsgN
。)