В настоящее время я пишу клиент/сервер UDP (на GNU/Linux ). Я использую sendto()
для отправки сообщений через сокет SOCK_DGRAM
, который не привязан к порту.
На странице руководства send (2 )указано, что:
On success, these calls return the number of characters sent. On error, -1 is returned, and errno is set appropriately.
Однако sendto всегда возвращает параметр длины, указывающий на успех. С сообщениями больше 65507(0xFFE3
)байт, он возвращает ошибку Message too long
.
Для сообщений, превышающих MTU в 1500 байт, сервер всегда получает (через 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 _отправить (0x7F000001, 1337, bigbuf,1501 ); который вернет 1501 при отправке только 1500 байт.