Для получения MTU в вашем интерфейсе, а не для обнаружения MTU пути, у вас есть struct ifreq. Одно из полей - ifr_mtu, и это поле предоставит вам MTU. Вы читаете это поле с помощью ioctl, SIOCGIFMTU для правильного интерфейса. (http://man7.org/linux/man-pages/man7/netdevice.7.html)
struct ifreq {
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char *ifr_data;
};
};
Пример:
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
int sock;
char *name = "enp0s3";
struct ifreq ifr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("Creating socket: %d\n", errno);
exit(-1);
}
ifr.ifr_addr.sa_family = AF_INET;
strcpy(ifr.ifr_name, name);
if (ioctl(sock, SIOCGIFMTU, (caddr_t)&ifr) < 0) {
printf("Error ioctl: %d\n", errno);
exit(-2);
}
printf("MTU is %d.\n", ifr.ifr_mtu);
close(sock);
return 0;
}
Сегодня, в общем, вы можете доверять MTU 1500 человек в Интернете, если вы не используете специальные технологии соединения, такие как Bluetooth или Zigbee. Вы можете использовать Path MTU Discovery и реализовать свой протокол на основе UDP с помощью ACK, чтобы проверить, получила ли другая сторона сообщение. Теперь реализация ACK и функций протокола, ориентированного на соединение, не совпадает с использованием TCP. Если вы можете делать все с UDP, оно легче TCP.
Edit: Для использования Path MTU Discovery, вы можете также использовать getsockopt с опцией IP_PMTUDISC_DO:
IP_MTU_DISCOVER (since Linux 2.2)
Set or receive the Path MTU Discovery setting for a socket.
When enabled, Linux will perform Path MTU Discovery as defined
in RFC 1191 on SOCK_STREAM sockets. For non-SOCK_STREAM
sockets, IP_PMTUDISC_DO forces the don't-fragment flag to be
set on all outgoing packets. It is the user's responsibility
to packetize the data in MTU-sized chunks and to do the
retransmits if necessary. The kernel will reject (with
EMSGSIZE) datagrams that are bigger than the known path MTU.
IP_PMTUDISC_WANT will fragment a datagram if needed according
to the path MTU, or will set the don't-fragment flag
otherwise.
Подробнее здесь: http://man7.org/linux/man-pages/man7/ip.7.html
А почему бы вам не рекомендуем, чтобы получить MTU во время бега -время? – FrozenHeart
Потому что у вас нет гарантии пути. Скорее всего, этот путь не изменится, но может, и если путь изменится, MTU может измениться. Если вы беспокоитесь об этом, установите бит DF и найдите сообщения об ошибках ICMP. Рекомендуемый размер UDP не является рекомендацией _my_. Наилучшее использование UDP - это небольшие дейтаграммы, так что мало теряется, когда пакеты теряются. Вот почему голос и видео с использованием UDP имеют очень маленькие дейтаграммы. –
Кроме того, перегрузка, означающая падение пакетов, _will_ постоянно меняется, и, вероятно, будет хуже в определенное время дня или ночи. Если у вас высокий уровень допуска к потерянным данным, используйте большую полезную нагрузку, иначе держите ее на низком уровне. –