Apparently, limiting file download speed it is not straightforward with the standard web helper classes provied by .NET - WebClient or HttpWebResponse. Someone even re-implemented a socket-based HTTP client to add this feature. While the latter might be a solution, relying on an incomplete and potentially buggy HTTP implementation is not something I like. Libcurl, on the other hand, has been around for ages and also has an option to limit the download speed. The library is ported to many OSes including Windows and wrapped for .NET as well, so I gave it a try.

CurlSharp, an improved fork of the official libcurl.NET, looked like a good start. The use is pretty straightforward - the wrapper comes with a few examples and pre-compiled libcurl binaries including dependencies:

libcurl.dll      libeay32.dll  msvcr120.dll  zlib1.dll
libcurlshim.dll  libssh2.dll   ssleay32.dll

The curl option for limiting download speed was missing from the wrapper at the time of writing, but it can be easily added. According to CURLOPT_MAX_RECV_SPEED_LARGE docs, the corresponding data type is curl_off_t which seems to match the signed 64-bit type, i.e. C# long.

// ----- CurlEasy.cs -----
private long _maxRecvSpeedLarge;

public long MaxRecvSpeedLarge
    get { return _maxRecvSpeedLarge; }
    set { setLongOption(CurlOption.MaxRecvSpeedLarge, ref _maxRecvSpeedLarge, value); }

// ----- CurlOption.cs -----
MaxRecvSpeedLarge = 30146, // CURLOPT_MAX_RECV_SPEED_LARGE

Now this can be used, for example in the EasyGet sample:

easy.BufferSize = 4096;
easy.MaxRecvSpeedLarge = 10*1024;

Setting a buffer size smaller than default makes it easier to see the data chunks going in at the reduced rate. Also, as the speed limit is most likely implemented through throttling, a big buffer with a small speed limit would yield in a large delay between downloading the chunks and the connection might timeout.

It is worth noting that when the speed is limited this way, the actual network usage is likely to be non-constant over time (contain bursts) because of the additional network buffering by OS. For example, here is what it looks like on my Windows 8.1 laptop:

Network usage

blog comments powered by Disqus