我目前正在编写一个 UDP 客户端/服务器(在 GNU/Linux 上)。我用于在尚未绑定到端口sendto()
的套接字上发送消息。SOCK_DGRAM
send(2) 联机帮助页指出:
成功时,这些调用返回发送的字符数。出错时,返回 -1,并适当设置 errno。
但是,sendto 总是返回它的长度参数,表示成功。对于大于 65507 ( 0xFFE3
) 字节的消息,它会返回Message too long
错误。
对于大于 1500 字节的 MTU 的消息,服务器总是(通过recvfrom()
)接收正好 1500 字节的消息,只是简单地截断消息,无需另行通知。
(为什么)这种行为是有意为之的,有没有办法在出现问题时得到通知?
我目前能想到的唯一解决方法是简单地假设 MTU 为 1500 字节并且从不发送更大的数据包。
这是相关的方法:
int udp_send(uint32_t dst, uint16_t port, char *msg, unsigned len) {
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0) {
perror("Could not open socket");
return -1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(dst);
int count = sendto(sock, msg, len, 0,
(struct sockaddr *) &addr, sizeof(addr));
printf("bytes sent: %d\n", count);
if(count < 0) {
perror("Could not send message");
return -3;
}
close(sock);
return count;
}
发生所描述的不良行为的调用将是 udp_send(0x7F000001, 1337, bigbuf, 1501); 仅发送 1500 个字节时将返回 1501。