I currently have the need to test the connection speed between two remote machines, so that I know when it is safe to transfer a large file from one to the other without significantly affecting service by causing long periods of downtime. I couldn’t find any software that did this easily, ran as a single executable (no installation) and was free, so I made one.
This currently only tests speed in one direction (upload from the client to the server) because I have symmetric connections on both machines, so either way should be exactly the same, and so that I can just write a client program and use netcat as a server to accept the packets and dump them to /dev/null. It is simple enough to convert this client into a server so that netcat becomes a client or so that they can be used together. Using netcat as a client probably requires quite a large pre-generated random file and may introduce a bottleneck of the hard drive read speed.
This could also be used in the home for something like testing the effect of wifi strength.
The client takes the command line arguments, connects to the server, generates some random data and sends that data repeatedly until the timer expires. It then prints out the results.
The command to use netcat to listen and ignore any data it receives is nc -lp 9000 > /dev/null though the -p isn’t always needed (it was needed on my Debian box but not my ESX 4 box).
An example of use of this program as a client is:
C:\>SpeedTestClient.exe 192.168.1.157 9000 Uploaded 1181614080 bytes in 10.015 seconds. 943875.45 kbps (943.88 mbps) 115219.17 kB/s (112.52 MB/s)
The results are given in kilobits per second and megabits per second (standard measurements for network speed), kilobytes per second and megabytes per second (more useful for knowing how long a file will take to transfer). In this example, a gigabit ethernet connection is getting roughly 944 mbps.
A few seconds later, VLC 1.0 is opened and paused, so nothing is playing and the test is run again. The results are quite interesting:
Uploaded 225083392 bytes in 10.015 seconds. 179797.02 kbps (179.80 mbps) 21947.88 kB/s ( 21.43 MB/s)
It says it is using next to no system resources when paused but it slows data transfer dramatically and this is with 8GiB of RAM, an otherwise idle CPU and no hard drives being used. When hard drives enter the equation this drops down to about 8MB/s (while VLC is still paused – I have particularly fast hard drives so I still get about 110MB/s when hard drives are used and VLC is turned off).
The code listing is as follows:
using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; namespace SpeedTest { class SpeedTestClient { static int Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Usage: SpeedTestClient <ip> <port> [<seconds>]"); return 1; } try { ulong bytes = 0; int startTime = Environment.TickCount; bool started = false; int timeout = 10; // Get the optional number of seconds argument if (args.Length > 2) timeout = int.Parse(args[2]); // Connect to the server via TCP TcpClient client = new TcpClient(); client.Connect(IPAddress.Parse(args[0]), int.Parse(args[1])); NetworkStream stream = client.GetStream(); // Generate some random data. Buffers too small will bottleneck. RandomNumberGenerator rng = RandomNumberGenerator.Create(); byte[] buffer = new byte[32768]; rng.GetBytes(buffer); while (true) { // Write the data stream.Write(buffer, 0, buffer.Length); // Start the timer only after some data has been sent if (!started) { startTime = Environment.TickCount; started = true; } // Add to the bytes counter bytes += (ulong)buffer.LongLength; if (Environment.TickCount - startTime >= timeout * 1000) break; } PrintFinalStats(startTime, Environment.TickCount, bytes); try { client.Close(); } catch (IOException) { /* Do nothing */ } } catch (Exception ex) { Console.Error.WriteLine(ex); return 1; } return 0; } static void PrintFinalStats(int start, int end, ulong bytes) { double seconds = (end - start) / 1000.0; ulong bits = bytes * 8; double bitsPerSecond = bits / seconds; double bytesPerSecond = bytes / seconds; string kbps = string.Format("{0:0.00}", bitsPerSecond / 1000); string mbps = string.Format("{0:0.00}", bitsPerSecond / 1000 / 1000); string kibs = string.Format("{0:0.00}", bytesPerSecond / 1024); string mibs = string.Format("{0:0.00}", bytesPerSecond / 1024 / 1024); int kPad = Math.Max(kbps.Length, kibs.Length); int mPad = Math.Max(mbps.Length, mibs.Length); Console.WriteLine("Uploaded {0} bytes in {1} seconds.", bytes, seconds); Console.WriteLine("{0} kbps ({1} mbps)", kbps.PadLeft(kPad), mbps.PadLeft(mPad)); Console.WriteLine("{0} kB/s ({1} MB/s)", kibs.PadLeft(kPad), mibs.PadLeft(mPad)); } } }
A compiled .net executable is available here.
P.S. always remember to turn off VLC before transferring files over the network.