对于 UDP 套接字,发送函数不会失败,但写入的数据仍然少于请求的数据,这是否真的会发生?

Can it realistically happen that for an UDP socket, the send function doesn't fail, but still writes less data than requested?

来自man 2 sendto

On success, these calls return the number of bytes sent. On error, -1 is returned, and errno is set appropriately.

我是否理解未能写入所有数据不被视为这些函数的失败,因此实际上可能会发生在写入 UDP 套接字时,send() 函数写入的数据少于请求的数据, 但失败的原因未在 errno?

中指定

或者我可以假定 send() 将 return -1 并适当地设置 errno,或者 return 请求发送的字节数?

换句话说:这个错误处理代码是否足够:

if(send(udp_sock_fd, buf, buflen, 0) == -1) {
  int err = errno;
  fprintf(stderr, "Send failed:\n");
  fprintf(stderr, strerror(err));
}

还是有必要这样写:

ssize_t bytes_send = send(udp_sock_fd, buf, buflen, 0);
if(bytes_send == -1) {
  int err = errno;
  fprintf(stderr, "Send failed:\n");
  fprintf(stderr, strerror(err));
} else if(bytes_send < buflen) {
  fprintf(stderr, "Incomplete send for unknown reason.\n");
}

不存在仅发送数据报的一部分的概念。要么全部消失,要么 none 消失。 OS 或网络驱动程序不会为您拆分数据报。返回发送的字符数必须只是一种礼貌,与其他 send API 函数保持一致。

同样来自手册页:

For sendto(), if the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.

显然,@Paul Bentley 已经提供了正确的答案,但如果您担心——即使这永远不会发生——它可能会出现一些罕见的错误情况,它可能至少对于特定的实现 (Linux),net/ipv4/udp.c 中的 udp_sendmsg 的代码(这是 UDP 套接字上的 send 最终调用的代码会有所帮助) 只有一个出口可以 return 一个非负值,它 return 是调用者提供的长度:

int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
        ... code that doesn't modify len ...
out:
        ...
        if (!err)
               return len;
        ...
}