Python中如何检测网络是否空闲

3
我正在制作一个基于Python的下载器。目前,我已经有了一个能够工作的基于多进程的控制台脚本。我想知道如何检测网络是否处于空闲状态。也就是说,用户没有使用网络(浏览、冲浪等)。

在这方面,它应该能够完成两件事:

  1. 检测到网络空闲时恢复下载。
  2. 检测到某些网络活动时暂停下载。

定义“空闲”的一种方式可能是在连续5分钟内,如果网络活动处于最大带宽的1%左右,则触发。

是否有更好的方法来检测网络是否空闲?


ifconfig eth0 可以给出接收和发送的字节数,如果定期运行,可以得到一个简单的指标。我会在 pexpect(或类似工具)中包装该命令并检查输出。不过,我也很想知道一个更好的方法来实现这个功能。 - Verma
这种方法的问题在于我无法知道哪个进程占用了多少网络。我想知道这一点,以便确定是浏览器或其他操作导致了网络流量而不是我的下载工具。 - MyPreciousss
@MyPreciousss,那是一个非常难开发的应用程序,我以前做过,但你必须访问每个操作系统的内核并检索每个进程的网络统计信息。等我发布我的答案时,我会详细说明。 - user1786283
2个回答

1
我建议使用psutil.network_io_counters模块:
返回网络I/O统计信息,包括以下属性的命名元组:
  • bytes_sent:发送的字节数
  • bytes_recv:接收的字节数
  • packets_sent:发送的数据包数
  • packets_recv:接收的数据包数
  • errin:接收时出错的总数
  • errout:发送时出错的总数
  • dropin:被丢弃的传入数据包总数
  • dropout:被丢弃的传出数据包总数(在OSX和BSD上始终为0)
如果pernic为True,则返回安装在系统上的每个网络接口的相同信息,作为以网络接口名称为键、上述命名元组为值的字典。
In [1]: import psutil
In [2]: psutil.network_io_counters(pernic=True)
Out[2]:
{'en0': iostat(bytes_sent=143391435L, bytes_recv=1541801914L,
               packets_sent=827983L, packets_recv=1234558L, errin=0L, errout=0L,
               dropin=0L, dropout=0),
 'gif0': iostat(bytes_sent=0L, bytes_recv=0L, packets_sent=0L, packets_recv=0L,
                errin=0L, errout=0L, dropin=0L, dropout=0),
 'lo0': iostat(bytes_sent=6143860L, bytes_recv=6143860L, packets_sent=55671L,
               packets_recv=55671L, errin=0L, errout=0L, dropin=0L, dropout=0),
 'p2p0': iostat(bytes_sent=0L, bytes_recv=0L, packets_sent=0L, packets_recv=0L,
                errin=0L, errout=0L, dropin=0L, dropout=0),
 'stf0': iostat(bytes_sent=0L, bytes_recv=0L, packets_sent=0L, packets_recv=0L,
                errin=0L, errout=0L, dropin=0L, dropout=0)
}

你可以跟踪想要监视的接口上发送和接收的字节数,这将为您提供网络是否空闲或繁忙的信息。

我该如何检测哪个进程正在占用多少资源?为了真正不对用户的网络使用造成干扰,我需要能够检测带宽是来自其他进程还是我的下载器。 - MyPreciousss
在Linux系统上,您可以检查/proc/PID/net/dev,并且还有一个bwmon。我知道Mac有nettop,但我不知道如何在BSD系统上做到这一点。 - Viktor Kerkez
或者您可以使用iptables根据源端口/目的地等标记数据包。 - Torxed
我会尝试一下,然后跟进。如果成功了,我也会将其标记为已解决。谢谢!@viktor kerkez - MyPreciousss

1

我有点怀疑这是否是正确的方法。你需要平均一段时间并经常检查,但仍然会遇到TOCTTOU问题(也就是,正好在你决定开始下一个下载片段的同时,用户点击了某个启动网络活动的东西)。

一种更好的方法可能是简单地限制你的应用程序下载带宽(到用户可配置的水平?),所以它只以X KB/s的速度下载。是的,它会慢一些,但实现起来会更容易,并且更容易理解其工作原理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接