Linux C语言 取得MTU (最大传输单元)

参照这篇博客: http://www.geekpage.jp/programming/linux-network/book/04/4-21.php

 * 查看主机当前网卡,哪块在使用.

ifconfig

  

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=3<RXCSUM,TXCSUM>
    inet6 ::1 prefixlen 128
    inet 127.0.0.1 netmask 0xff000000
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
    nd6 options=1<PERFORMNUD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether a4:5e:60:d6:57:17
    inet6 fe80::a65e:60ff:fed6:5717%en0 prefixlen 64 scopeid 0x4
    inet 192.168.16.103 netmask 0xffffff00 broadcast 192.168.16.255
    nd6 options=1<PERFORMNUD>
    media: autoselect
    status: active
en1: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500
    options=60<TSO4,TSO6>
    ether 4a:00:01:33:73:10
    media: autoselect <full-duplex>
    status: inactive
en2: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500
    options=60<TSO4,TSO6>
    ether 4a:00:01:33:73:11
    media: autoselect <full-duplex>
    status: inactive
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
    ether 06:5e:60:d6:57:17
    media: autoselect
    status: inactive
awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484
    ether 7a:00:b6:6c:ea:a0
    inet6 fe80::7800:b6ff:fe6c:eaa0%awdl0 prefixlen 64 scopeid 0x8
    nd6 options=1<PERFORMNUD>
    media: autoselect
    status: active
bridge0: flags=8822<BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 1500
    options=63<RXCSUM,TXCSUM,TSO4,TSO6>
    ether a6:5e:60:6d:62:00
    Configuration:
        id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
        maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
        root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
        ipfilter disabled flags 0x2
    member: en1 flags=3<LEARNING,DISCOVER>
            ifmaxaddr 0 port 5 priority 0 path cost 0
    member: en2 flags=3<LEARNING,DISCOVER>
            ifmaxaddr 0 port 6 priority 0 path cost 0
    media: <unknown type>
    status: inactive
ifconfig 输出
ifconfig en0

  

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	ether a4:5e:60:d6:57:17
	inet6 fe80::a65e:60ff:fed6:5717%en0 prefixlen 64 scopeid 0x4
	inet 192.168.16.103 netmask 0xffffff00 broadcast 192.168.16.255
	nd6 options=1<PERFORMNUD>
	media: autoselect
	status: active

可以看到en0网卡有有效的ip地址net 192.168.16.103, 说明这块网卡在使用, Linux环境通常是eth0.

* 创建文件main.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>

int main(int argc, const char * argv[]) {
    int fd;
    struct ifreq ifr;

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    
    strncpy(ifr.ifr_name, "en0", IFNAMSIZ-1);   // eth0
    if (ioctl(fd, SIOCGIFMTU, &ifr)) {
        perror("ioctl");
        return 1;
    }
    close(fd);
    
    printf("%d
", ifr.ifr_mtu);
    
    return 0;
}

  

* 编译运行

1500

Program ended with exit code: 0

 

得出MTU为1500

 

* 一些函数原型

 

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

socket.h

/*

 * Types

 */

#define SOCK_STREAM 1 /* stream socket */

#define SOCK_DGRAM 2 /* datagram socket */

#define SOCK_RAW 3 /* raw-protocol interface */

 

// ...

/*

 * [XSI] Structure used by kernel to store most addresses.

 */

struct sockaddr {

__uint8_t sa_len; /* total length */

sa_family_t sa_family; /* [XSI] address family */

char sa_data[14]; /* [XSI] addr value (actually larger) */

};

 

int accept(int, struct sockaddr * __restrict, socklen_t * __restrict)

__DARWIN_ALIAS_C(accept);

int bind(int, const struct sockaddr *, socklen_t) __DARWIN_ALIAS(bind);

int connect(int, const struct sockaddr *, socklen_t) __DARWIN_ALIAS_C(connect);

 

////////////////////////////////////////////////////////////////

if.h

////////////////////////////////////////////////////////////////

/*

 * Interface request structure used for socket

 * ioctl's.  All interface ioctl's must have parameter

 * definitions which begin with ifr_name.  The

 * remainder may be interface specific.

 */

struct ifreq {

#ifndef IFNAMSIZ

#define IFNAMSIZ IF_NAMESIZE

#endif

char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */

union {

struct sockaddr ifru_addr;

struct sockaddr ifru_dstaddr;

struct sockaddr ifru_broadaddr;

short ifru_flags;

int ifru_metric;

int ifru_mtu;

int ifru_phys;

int ifru_media;

int ifru_intval;

caddr_t ifru_data;

struct ifdevmtu ifru_devmtu;

struct ifkpi ifru_kpi;

u_int32_t ifru_wake_flags;

u_int32_t ifru_route_refcnt;

int ifru_cap[2];

} ifr_ifru;

#define ifr_addr ifr_ifru.ifru_addr /* address */

#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */

#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */

 

/////////////////////////////////////////////////

ioctl -- control device

SYNOPSIS
#include <sys/ioctl.h>

int ioctl(int fildes, unsigned long request, ...);

 

原文地址:https://www.cnblogs.com/mingzhanghui/p/9341473.html