如何通过代码(在python中)找到网络的mtu值?

问题描述:

我必须编写一个代码,我需要在Python中使用udp协议发送数据。我需要将数据包大小设置为网络的MTU值。有没有什么办法可以决定在python中编写一些代码的网络的MTU值?如何通过代码(在python中)找到网络的mtu值?

这个答案是从 http://books.google.co.il/books?id=9HGUc8AO2xQC&pg=PA31&lpg=PA31&dq#v=onepage&q&f=false (第31页)采取

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 
hostName = #ip here 
Port = 9999 
s.connect((hostName, Port)) 
s.setsockopt(socket.IPPROTO_IP, IN.IP_MTU_DISCOVER, IN.IP_PMTUDISC_DO) 
try: 
    s.send('#' * 1473) 
except socket.error: 
    print 'The message did not make it' 
    option = getattr(IN, 'IP_MTU', 14) 
    print 'MTU:', s.getsockopt(socket.IPPROTO_IP, option) 
else: 
    print 'The big message was sent! Your network supports really big packets!' 
+0

是的,它的工作,但是在udp协议中使用连接是否正确? –

+0

@RahulKatare:是的,它是:“要获得路径MTU的初始估计,使用connect(2)将数据报套接字连接到目标地址,并通过使用IP_MTU选项调用getsockopt(2)来检索MTU。”。 –

+0

什么是IN? '输入IN'不起作用 - 使用'IN'搜索并不容易。 –

有一个github上,依据提供此功能:

import re 
import socket 
import struct 
import logging 
import subprocess 
from fcntl import ioctl 

SIOCGIFMTU = 0x8921 
SIOCSIFMTU = 0x8922 

log = logging.getLogger(__name__) 

def get_mtu_for_address(ip): 
    routeinfo = subprocess.check_output(['ip', 'route', 'get', ip]) 
    dev = re.search('.*dev (\w+) .*', routeinfo).groups()[0] 
    mtuinfo = subprocess.check_output(['ip', 'link', 'show', dev]) 
    mtu = re.search('.*mtu ([0-9]+) .*', mtuinfo).groups()[0] 
    return int(mtu) 

class Iface: 
    def __init__(self, ifname): 
     self.ifname = ifname 

    def get_mtu(self): 
     '''Use socket ioctl call to get MTU size''' 
     s = socket.socket(type=socket.SOCK_DGRAM) 
     ifr = self.ifname + '\x00'*(32-len(self.ifname)) 
     try: 
      ifs = ioctl(s, SIOCGIFMTU, ifr) 
      mtu = struct.unpack('<H',ifs[16:18])[0] 
     except Exception, s: 
      log.critical('socket ioctl call failed: {0}'.format(s)) 
      raise 

     log.debug('get_mtu: mtu of {0} = {1}'.format(self.ifname, mtu)) 
     self.mtu = mtu 
     return mtu 

    def set_mtu(self, mtu): 
     '''Use socket ioctl call to set MTU size''' 
     s = socket.socket(type=socket.SOCK_DGRAM) 
     ifr = struct.pack('<16sH', self.ifname, mtu) + '\x00'*14 
     try: 
      ifs = ioctl(s, SIOCSIFMTU, ifr) 
      self.mtu = struct.unpack('<H',ifs[16:18])[0] 
     except Exception, s: 
      log.critical('socket ioctl call failed: {0}'.format(s)) 
      raise 

     log.debug('set_mtu: mtu of {0} = {1}'.format(self.ifname, self.mtu)) 

     return self.mtu 


if __name__ == "__main__": 
    import sys 
    logging.basicConfig() 

    mtu = None 
    if len(sys.argv) > 2: 
     dev,mtu = sys.argv[1:] 
    elif len(sys.argv) > 1: 
     dev = sys.argv[1] 
    else: 
     dev = 'eth0' 

    iface = Iface(dev) 
    if mtu is not None: 
     iface.set_mtu(int(mtu)) 

    print dev,'mtu =',iface.get_mtu() 

来源:https://gist.github.com/nzjrs/8934855