博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Python根据网速自动切换网关
阅读量:6477 次
发布时间:2019-06-23

本文共 5905 字,大约阅读时间需要 19 分钟。

hot3.png

公司里装了两条不同的宽带,根据使用的情况,比如拨VPN,或者使用人数过多,网速不行了就要切换下。每次手动去切换很不方便,而且网速也很难判断。这里分享下如何用Python检测网速,然后自动切换网关。

参考原文:

作者:

翻译:yushulx

使用speedtest-cli测试网速

相信很多人都用过speedtest.net来测试网络速度,是一个Python开源项目。通过链接speedtest.net来检测上传速度和下载速度。

安装

pip install speedtest-cli

或者

easy_install speedtest-cli

测试网速

安装之后就可以通过命令行来测试下网速:

speedtest-cli --bytes

28141038_p9j7.png

根据log我们大概可以推测下这个程序的工作步骤:

  1.  从speedtest.net读取配置文件。

  2. 获得一个server列表。

  3. 找到最近的server作为最优选择用来测试速度。

这种最优方式适合检测网络的最大下载速度。而我现在需要的是根据网络访问速度切换网关,比如我需要经常访问国外某个网站,这个最大下载速度就没有意义了。要检测速度,我可以随意设置一些这个网站上的图片资源作为测试数据,而并不需要使用speedtest.net。

自定义函数用于检测网速

通过学习源码,我们可以自己重写一个网速测试函数。找到 {Python Installation Directory}\Lib\site-packages\speedtest_cli.py,根据speedtest()创建的函数很简单:

def testSpeed(urls):    speedtest_cli.shutdown_event = threading.Event()    signal.signal(signal.SIGINT, speedtest_cli.ctrl_c)     print "Start to test download speed: "    dlspeed = speedtest_cli.downloadSpeed(urls)    dlspeed = (dlspeed / 1000 / 1000)    print('Download: %0.2f M%s/s' % (dlspeed, 'B'))     return dlspeed
 

原始代码是先找到最佳服务器,然后从上面获取URL资源。这里只需要随便设置我需要的资源:

urls = ["http://www.dynamsoft.com/assets/images/logo-index-dwt.png", "http://www.dynamsoft.com/assets/images/logo-index-dnt.png", "http://www.dynamsoft.com/assets/images/logo-index-ips.png", "http://www.codepool.biz/wp-content/uploads/2015/06/django_dwt.png", "http://www.codepool.biz/wp-content/uploads/2015/07/drag_element.png"]
 

看看源码中的下载速度是如何计算的?

def downloadSpeed(files, quiet=False):    """Function to launch FileGetter threads and calculate download speeds"""     start = timeit.default_timer()     def producer(q, files):        for file in files:            thread = FileGetter(file, start)            thread.start()            q.put(thread, True)            if not quiet and not shutdown_event.isSet():                sys.stdout.write('.')                sys.stdout.flush()     finished = []     def consumer(q, total_files):        while len(finished) < total_files:            thread = q.get(True)            while thread.isAlive():                thread.join(timeout=0.1)            finished.append(sum(thread.result))            del thread     q = Queue(6)    prod_thread = threading.Thread(target=producer, args=(q, files))    cons_thread = threading.Thread(target=consumer, args=(q, len(files)))    start = timeit.default_timer()    prod_thread.start()    cons_thread.start()    while prod_thread.isAlive():        prod_thread.join(timeout=0.1)    while cons_thread.isAlive():        cons_thread.join(timeout=0.1)    return (sum(finished) / (timeit.default_timer() - start))
 
  1. 在线程中读取读取图片资源。

  2. 把线程放入阻塞的队列中。

  3. 从队列中把线程的结果一个个读取出来。

  4. speed = total file sizes / total time cost

查询网络适配器设置,并设置网关

如何用Python设置网关?在StackOverflow上可以找到解答。推荐的方法是使用WMI (Windows Management Instrumentation)

安装

Win32网络适配器设置

很多人的电脑上会看到很多的网络适配器,比如无线网卡的,虚拟网卡的,以太网卡的等等。每个适配器都有很多属性,看下微软的定义:

[Provider("CIMWin32")]class Win32_NetworkAdapterConfiguration : CIM_Setting{  boolean  ArpAlwaysSourceRoute;  boolean  ArpUseEtherSNAP;  string   Caption;  string   DatabasePath;  boolean  DeadGWDetectEnabled;  string   DefaultIPGateway[];  uint8    DefaultTOS;  uint8    DefaultTTL;  string   Description;  boolean  DHCPEnabled;  datetime DHCPLeaseExpires;  datetime DHCPLeaseObtained;  string   DHCPServer;  string   DNSDomain;  string   DNSDomainSuffixSearchOrder[];  boolean  DNSEnabledForWINSResolution;  string   DNSHostName;  string   DNSServerSearchOrder[];  boolean  DomainDNSRegistrationEnabled;  uint32   ForwardBufferMemory;  boolean  FullDNSRegistrationEnabled;  uint16   GatewayCostMetric[];  uint8    IGMPLevel;  uint32   Index;  uint32   InterfaceIndex;  string   IPAddress[];  uint32   IPConnectionMetric;  boolean  IPEnabled;  boolean  IPFilterSecurityEnabled;  boolean  IPPortSecurityEnabled;  string   IPSecPermitIPProtocols[];  string   IPSecPermitTCPPorts[];  string   IPSecPermitUDPPorts[];  string   IPSubnet[];  boolean  IPUseZeroBroadcast;  string   IPXAddress;  boolean  IPXEnabled;  uint32   IPXFrameType[];  uint32   IPXMediaType;  string   IPXNetworkNumber[];  string   IPXVirtualNetNumber;  uint32   KeepAliveInterval;  uint32   KeepAliveTime;  string   MACAddress;  uint32   MTU;  uint32   NumForwardPackets;  boolean  PMTUBHDetectEnabled;  boolean  PMTUDiscoveryEnabled;  string   ServiceName;  string   SettingID;  uint32   TcpipNetbiosOptions;  uint32   TcpMaxConnectRetransmissions;  uint32   TcpMaxDataRetransmissions;  uint32   TcpNumConnections;  boolean  TcpUseRFC1122UrgentPointer;  uint16   TcpWindowSize;  boolean  WINSEnableLMHostsLookup;  string   WINSHostLookupFile;  string   WINSPrimaryServer;  string   WINSScopeID;  string   WINSSecondaryServer;};
 

找到了某个特定属性所对应的值,我们就可以很容易找到目标适配器了。我是这样查找的:

  1. 右键目标网络适配器。

  2. 选择配置。

  3. 点击详细。

  4. 看一下属性列表及对应的值。

最后选择了设备描述Realtek PCIe GBE Family Controller。

28141040_1nwM.png

用Python查询Windows IP和网关

wmiObj = wmi.WMI()sql = "select IPAddress,DefaultIPGateway from Win32_NetworkAdapterConfiguration where Description=\"Realtek PCIe GBE Family Controller\" and IPEnabled=TRUE"configurations = wmiObj.query(sql)
 

设置Windows网关

configurations = wmiObj.Win32_NetworkAdapterConfiguration(Description="Realtek PCIe GBE Family Controller", IPEnabled=True)configuration = configurations[0]ret = configuration.SetGateways(DefaultIPGateway=[gateway])
 

请注意脚本必须用管理员权限来执行,不然设置会失败。记得查看返回值。

for gateway in gateways:        settingReturn = setGateway(wmiObj, gateway)         if (settingReturn[0] != 0):            print "Setting failed"            return         print "Set gateway: " + gateway        dlspeed = testSpeed(urls)        option = (gateway, dlspeed)        print "Network option: " + str(option)         if (option[1] > bestChoice[1]):            bestChoice = option

把Python脚本转换成可执行EXE

如何把Python程序分发给别人使用如果他们并没有安装Python程序以及依赖库?使用Py2exe 可以很容易把Python脚本转换成exe文件。

安装

转换Python脚本

新建setup.py:

from distutils.core import setupimport py2exesetup(console=['network.py'])
 

执行下面的命令:

python setup.py py2exe

目录中会生成一个dist 文件夹:

28141041_EwwV.png

记得执行程序的时候必须要用管理员权限。

源码

转载于:https://my.oschina.net/yushulx/blog/484663

你可能感兴趣的文章
给定单链表,检测是否有环等系列考题
查看>>
AngularJS
查看>>
例行报告
查看>>
ssh全注解整合
查看>>
R语言离群值处理分析
查看>>
走向DBA[MS SQL Server篇] - 从SQL语句的角度提高数据库的访问性能
查看>>
[转载]ASP.NET MVC3 及其学习资源
查看>>
JavaScript 中对变量和函数声明的“提前”
查看>>
非阻塞算法-栈
查看>>
java 打开记事本
查看>>
狗 日 的 360
查看>>
Policy in Reinforcement Learning
查看>>
.net 通过NPOI或MyXls把DataTable导出到Excel
查看>>
GBK编码和UTF-8编码互转的大坑
查看>>
SQL Server Profiler(一)
查看>>
利用@media screen实现网页布局的自适应
查看>>
ajax取json数据——简单的
查看>>
css一像素问题
查看>>
使用Eclipse进行远程调试【转】
查看>>
【POJ】2418 Hardwood Species
查看>>