Ever wanted to know which process is using the network bandwidth most? I googled and learned that, on Linux,
iftop seems to be able to tell which port is the busiest. But 'iftop' doesn't seems to be compilable on
cygwin. So, I googled more and found several similar Windows GUI apps. But they are all shareware and they are overkill for my purpose anyway. So, I wrote a perl to parse
tcpdump output to aggregate by local ports.
On Windows, it requires 'windump'.
WinDump: tcpdump for WindowsWinDump is the Windows version of tcpdump, the command line network analyzer for UNIX. WinDump is fully compatible with tcpdump
The output will look like this.
$ perl /c/e/tmp/active-port.pl 5 1000
962 packets other, e.g.) arp 57850 bytes.
10 packets 220.14.81.26:1275 4526 bytes.
10 packets 220.14.81.26:1068 906 bytes.
10 packets 220.14.81.26:1256 570 bytes.
4 packets 220.14.81.26:1273 228 bytes.
2 packets 220.14.81.26:21 128 bytes.
1 packets 220.14.81.26:1026 636 bytes.
1 packets other, e.g.)UDP broadcast 590 bytes.
Here's perl script. Borrowed code from
here and
here.
#!/usr/bin/perl -w
#
# Parse tcpdump and say which ports are more active
# Usage example: perl active-port.pl '\\Device\\NPF_{55899BD0-EC52-4066-ABA7-53849ACAA19A}' 100 | sort -t $'\t' -k 3nr
use strict;
if ($#ARGV != 1) {
die "$0: Need exactly two arguments. Interface name/# and packet count to capture.\n";
}
my $tcpdump = "tcpdump";
my $index=0, my @local_ipaddrs, my $address;
if (defined $ENV{OS} && $ENV{OS} =~ "Windows_NT") {
use Sys::Hostname;
$tcpdump = "windump";
my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname hostname;
foreach $address (@addrs) {
my ($a,$b,$c,$d) = unpack('C4',$address);
$local_ipaddrs[$index++] = "$a.$b.$c.$d";
}
} else {
require IO::Interface::Simple;
my @interfaces = IO::Interface::Simple->interfaces;
loop: for my $if (@interfaces) {
next loop if ( !defined $if->address );
$local_ipaddrs[$index++] = $if->address;
}
}
open(TCPDUMP, "$tcpdump -i $ARGV[0] -c $ARGV[1] -nntqep 2>/dev/null |");
eof(TCPDUMP) && die "$0: Could not run $tcpdump: $?\n";
my %activity, my %bytes;
while (<TCPDUMP>) {
my ($link_level_length, $rest) = ($_ =~ /^[0-9a-f:]{17}\s>\s[0-9a-f:]{17},\s\S+,\slength\s(\d+):\s(.*)/);
if (my ($addrport1,$addrport2) = ($rest =~ /(\d+\.\d+\.\d+\.\d+\.\d+)\s>\s(\d+\.\d+\.\d+\.\d+\.\d+):/)) {
my $local;
local_ipaddrses: foreach $address (@local_ipaddrs) {
if ($addrport1 =~ /^$address\./) {
$addrport1 =~ s/(.*)\./$1:/;
$activity{$addrport1}++; $bytes{$addrport1}+=$link_level_length;
$local = "true";
last local_ipaddrses;
}
}
local_ipaddrses: foreach $address (@local_ipaddrs) {
if ($addrport2 =~ /^$address\./) {
$addrport2 =~ s/(.*)\./$1:/;
$activity{$addrport2}++; $bytes{$addrport2}+=$link_level_length;
$local = "true";
last local_ipaddrses;
}
}
if (!defined $local) {
$activity{"other, e.g.)UDP broadcast"}++; $bytes{"other, e.g.)UDP broadcast"}+=$link_level_length;
}
}
else {
$activity{"other, e.g.) arp"}++; $bytes{"other, e.g.) arp"}+=$link_level_length;
}
}
foreach my $addr_n_port ( sort { $activity{$b} <=> $activity{$a} } keys %activity) {
print "$activity{$addr_n_port} packets\t$addr_n_port\t\t$bytes{$addr_n_port}\tbytes.\n";
}
exit 0;