7

I'm wondering whether there is a programmatic way to obtain a measure of the full bandwidth used when sending data through a TCP stream. Since I cannot seem to know how the network stack would divide the stream into packets, or when it sends a TCP SYN or ACK or many of the things it does in the background for you, I can only get a rough estimate for this.

The only solution I can think of is to actually sniff the interface, but I would like to think that the stack can already collect this stats for me.

This is running in Java under either Windows or Linux (of course, a portable solution would be preferred), but I can JNI-ize a C/C++ answer so that (and OS API calls) is a fine answer too. Thank you!

Ismael C
  • 111
  • 2
  • 6
  • 1
    If you are asking about OS tools that may be available to gather this info, this is really a serverfault question. – T.E.D. Feb 03 '10 at 16:08
  • 1
    No I'm not asking about OS tools, I'm asking about an API which might gather this info. – Ismael C Feb 04 '10 at 23:33
  • Well, any solution for that other than sniffing? I have an app that collects audio/video streams, and I would really benefit from knowing the exact bandwidth that is used due to network congestion and TCP overhead. – Daniel Mošmondor Mar 26 '11 at 18:26
  • Yeah, I need this to be for .NET. – Daniel Mošmondor Mar 26 '11 at 18:32
  • @Daniel: You need to ask your own question. You can use a link to this one and explain how it's similar and how it's different (different platform, at least), but don't hijack. – Ben Voigt Apr 12 '11 at 02:12

7 Answers7

3

[Windows specific answer]

On Windows you can consider looking at ETW (Event Tracing for Windows). In general, ETW is the technology used to provide tracing/logging information on Windows, and most Microsoft software is already instrumented with ETW providers that you can use. In your case, I think the Microsoft-Windows-TCPIP provider has information (e.g. local/remote address and port, operation, bytes sent/received, etc) that might be helpful for you.

For example, I was able to start collecting the TCPIP events to a file using the command:

logman start MyTcpipLog -p Microsoft-Windows-TCPIP -ets

And stop with

logman stop MyTcpipLog -ets

Then the MyTcipipLog.etl file can be opened using a number of different tools (e.g. xperf), but there are APIs that you can use to parse this file yourself.

If you wanted to be doing this at runtime, you can create a "real-time" ETW session to process the events as they come in.

If you're new to ETW, here's a helpful article on MSDN that I used.

Matt
  • 4,318
  • 1
  • 27
  • 28
1

Can't speak for Windows, but the Linux kernel, as of 2.6.37, is not collecting the statistics you are looking for. Per-socket stats would have to be in struct sock or its descendants and I am not seeing any transmit/receive counters there:

http://lxr.linux.no/linux+v2.6.37.3/include/net/sock.h#L224

dmitrii
  • 188
  • 6
  • Some of these are exported to /proc/net/tcp, see [here](http://lkml.indiana.edu/hypermail/linux/kernel/0409.1/2166.html). But there are no explicit counters... – Mackie Messer Apr 02 '11 at 12:37
0

On Linux, this is fairly trivial information for root to get (simply create a netfilter chain matching your traffic, you can use a process id match, for example, later read the counters associated with the chain). Doing it with limited permissions may well be impossible.

Not sure for Windows.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

It should be possible to use conntrack accounting to measure packets and bytes on a per connection basis. Then the information should be queried using netlink sockets. Get the information about your socket with getsockname and getpeername, and use this information to look up the connection tracking entry.

This requires recent enough kernel, conntrack module loaded and libnetfilter_conntrack.

Also, the same information is available in /proc/net/nf_conntrack, but that file shouldn't be parsed too frequently.

And there's a tool named "conntrack" that gives you access to this information from the command line.

bazsi77
  • 521
  • 2
  • 6
0

You could look into consuming Perfmon counters. The Network Interface/Current Bandwidth counter might be what you need. You can create and consume performance counters from .NET code.

Kevin Hsu
  • 1,726
  • 11
  • 14
-1

Well TCP is a fixed data gram which is specified by the MTU. If you know your MTU, you can figure out how many data grams you have to transmit and TCP follows a standard model for acknowledgment.

Here is a good article on that help figure out the overhead of data transmission, which includes the overhead of Ethernet and the other layers of the stack.

Kitson
  • 1,650
  • 1
  • 18
  • 36
  • Well, not exactly. Run tcpdump on your ssh connection - are all the segments of the same size? – Nikolai Fetissov Feb 03 '10 at 16:22
  • I should clarify to say there is a maximum segment size which is determined by the MTU. If the amount of data the application wishes to send exceeds the MSS determined by the MTU the packet becomes "fragmented". But essentially if you know how much you are wishing to send at a time and the MTU on the network, you can figure out the total amount of overhead needed to transmit your data. – Kitson Feb 03 '10 at 18:16
  • 2
    Yes ... that would be the *minimum* possible overhead, not the actual one, which depends on how the app uses the network over time. Say I need to transfer 40 bytes one-way every minute. Ignoring connection handshake and tear-down, I'd probably end up with an 80 byte packets (20 for IPv4 header, 20 for TCP header without options, 40 for data). That's already 100% of overhead, not even counting the ACKs coming back that carry no application data at all. – Nikolai Fetissov Feb 03 '10 at 20:13
  • 1
    Nikolai is right on it. I can already get an estimate (the minimum possible overhead as he said), but I'd like to be able to measure the actual overhead incurred by TCP's whole enchilada. – Ismael C Feb 04 '10 at 23:41
  • MTU isn't at all visible with TCP, it's a stream socket protocol. You just need to make sure that you have enough transmit buffer. Also, the answer poster is also completely wrong about TCP. It's like buckets full of water, filling up a bucket with a hole in it with the received information slowly pouring out. If you want X bytes of information when you call recv(), you might get some of one packet, and some of several others. I think you should stop spreading misinformation and talking about subjects which are clearly above your head. – Chris Dennett Apr 29 '10 at 21:08
-1

If this TCP stream is the only thing going through your interface, you could just query the interface statistics (bytes sent/received) and measure the time yourself (+do the math).

smilingthax
  • 5,254
  • 1
  • 23
  • 19