C# 如何计算HttpWebRequest花费的出站和入站internet流量
我有下面的函数来获取页面。我的问题是我想计算一下上网的费用 入站(下载)和出站流量(已发送) 我该怎么做?多谢各位 我的职能C# 如何计算HttpWebRequest花费的出站和入站internet流量,c#,wpf,httpwebrequest,webrequest,network-traffic,C#,Wpf,Httpwebrequest,Webrequest,Network Traffic,我有下面的函数来获取页面。我的问题是我想计算一下上网的费用 入站(下载)和出站流量(已发送) 我该怎么做?多谢各位 我的职能 public static string func_fetch_Page(string srUrl, int irTimeOut = 60, string srRequestUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0", str
public static string func_fetch_Page(string srUrl, int irTimeOut = 60,
string srRequestUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0",
string srProxy = null)
{
string srBody = "";
string srResult = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(srUrl);
request.Timeout = irTimeOut * 1000;
request.UserAgent = srRequestUserAgent;
request.KeepAlive = true;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
WebHeaderCollection myWebHeaderCollection = request.Headers;
myWebHeaderCollection.Add("Accept-Language", "en-gb,en;q=0.5");
myWebHeaderCollection.Add("Accept-Encoding", "gzip, deflate");
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
using (WebResponse response = request.GetResponse())
{
using (Stream strumien = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(strumien))
{
srBody = sr.ReadToEnd();
srResult = "success";
}
}
}
}
catch ()
{
}
return srBody;
}
C#.net 4.5 WPF应用程序
@Simon Mourier我如何计算花费的流量
public static long long_GlobalDownload_KByte = 0;
public static long long_GlobalSent_KByte = 0;
Time _timer_fetch_download_upload = new Timer(getDownload_Upload_Values, null, 0, 100 * 1000);
public static void getDownload_Upload_Values(Object state)
{
using (Process p = Process.GetCurrentProcess())
{
foreach (var cnx in TcpConnection.GetAll().Where(c => c.ProcessId == p.Id))
{
Interlocked.Add(ref long_GlobalDownload_KByte, Convert.ToInt64(cnx.DataBytesIn));
Interlocked.Add(ref long_GlobalSent_KByte, Convert.ToInt64(cnx.DataBytesOut));
}
}
}
由于某些不可预测的以太网通信量等原因,很难确切知道发生了多少网络通信量,但本质上任何HTTP请求的要点都是:
method request-uri version
* (header : value)
CRLF
body
因此,您可以计算出请求字符串的长度:
HttpWebRequest req = ...;
StringBuilder requestText = new StringBuilder();
requestText.AppendFormat("{0} {1} HTTP/{2}.{3}", req.Method, req.RequestUri, req.ProtocolVersion.Major, req.ProtocolVersion.Minor);
requestText.AppendLine();
foreach (var header in req.Headers)
{
requestText.AppendFormat("{0}: {1}", v, webReq.Headers[v]);
requestText.AppendLine();
}
requestText.AppendLine();
// somehow add on the contents of the request stream, or just add that length later. I won't put that in this code because of stream positioning and all that
return System.Text.Encoding.UTF8.GetByteCount(requestText.ToString());
那么,对于响应端来说,情况就非常相似了。HTTP响应的格式为:
version status-code status-description
* (header : value)
CRLF
body
所以
在这里,有一点决定要做。您需要获得响应主体的长度。可能有更多的选择,但我现在想的是你可以:
流
包装器,获取复制的字节数。这样,您就不必担心分块传输,编写代码也会很有趣content-length
标题,尽管如果没有该标题,您将无法获得它,就像传输编码:chunked
一样内存流
,然后将其作为新响应流传递,同时在途中获取长度// webReq.AutomaticDecompression = DecompressionMethods.None; is required for this, since we're handling that decompression ourselves.
using (var respStream = resp.GetResponseStream())
using (var memStream = new MemoryStream())
{
respStream.CopyTo(memStream);
using (var gzip = new System.IO.Compression.GZipStream(respStream, System.IO.Compression.CompressionMode.Decompress))
using (var reader = new StreamReader(gzip))
{
var content = reader.ReadToEnd();
// you may or may not actually care about this, depending on whether this is just light testing or if you'll actually have these metrics in production
}
return System.Text.Encoding.UTF8.GetByteCount(responseText.ToString()) + memStream.Length;
}
现在,我看到了一些注意事项。其他人可能会注意到更多,如果有人发表评论,我会将他们添加进来
- 正如我在本文开头提到的,一个请求的网络流量可能比它告诉您的要多李>
- 根据客户机和服务器的不同,您可能会发现实际的头可以用不同数量的空格列出。我不认为这超出了HTTP规范,即使是这样,人们也会这么做。因此,有可能,例如,您会看到一个服务器集
和另一个集内容类型:text/html
。因为我们使用UTF-8,所以至少有一个字节的差异。同样,很少,但这是一个可能的差异内容类型:text/html
此外,如果有人碰巧注意到这里有任何打字错误,我确实复制粘贴了几次,我想我都得到了,但请随时通知我或修复它们。如果您的客户端应用程序正在与已知的IIS服务器通信,那么我会尝试从IIS日志中获取这些数据。检查cs字节(客户端到服务器字节,又称请求字节)和sc字节(服务器到客户端字节,又称响应字节) 一个Windows API可以为您提供以下信息:用于IPV4连接和相关IPV6 GetPertCP6ConnectionStats函数。请注意,您需要使用之前才能获得任何统计,这通常需要管理员权限 要获取所有连接的列表,可以使用函数。它还可以为您提供非常有用的连接进程id 这些都是本机API,不太容易使用,但我创建了一个TcpConnection类来封装所有这些。可在一个名为IPStats的小型WPF应用程序中获得: 因此,这里的困难在于从连接列表中将.NET HttpWebRequest链接到TcpConnection。 在连接存在之前,您无法获取任何stat,但是一旦创建了连接,您就可以使用如下代码获取相应的stat:
static IEnumerable<TcpConnection> GetProcessConnection(IPEndPoint ep)
{
var p = Process.GetCurrentProcess();
return TcpConnection.GetAll().Where(c => ep.Equals(c.RemoteEndPoint) && c.ProcessId == p.Id);
}
HttpWebRequest req = ...
// this is how you can get the enpoint, or you can also built it by yourself manually
IPEndPoint remoteEndPoint;
req.ServicePoint.BindIPEndPointDelegate += (sp, rp, rc) =>
{
remoteEndPoint = rp;
return null;
};
// TODO: here, you need to connect, so the connection exists
var cnx = GetProcessConnection(remoteEndPoint).FirstOrDefault();
// access denied here means you don't have sufficient rights
cnx.DataStatsEnabled = true;
// TODO: here, you need to do another request, so the values are incremented
// now, you should get non-zero values here
// note TcpConnection also has int/out bandwidth usage, and in/out packet usage.
Console.WriteLine("DataBytesIn:" + cnx.DataBytesIn);
Console.WriteLine("DataBytesOut:" + cnx.DataBytesOut);
// if you need all connections in the current process, just do this
ulong totalBytesIn = 0;
ulong totalBytesOut = 0;
Process p = Process.GetCurrentProcess();
foreach (var cnx in TcpConnection.GetAll().Where(c => c.ProcessId == p.Id))
{
totalBytesIn += cnx.DataBytesIn;
totalBytesOut += cnx.DataBytesOut;
}
静态IEnumerable GetProcessConnection(IPEndPoint ep)
{
var p=Process.GetCurrentProcess();
返回TcpConnection.GetAll(),其中(c=>ep.Equals(c.RemoteEndPoint)和&c.ProcessId==p.Id);
}
HttpWebRequest请求=。。。
//这是您获取enpoint的方式,或者您也可以自己手动构建它
IPEndPoint远程端点;
req.ServicePoint.BindIPEndPointDelegate+=(sp、rp、rc)=>
{
remoteEndPoint=rp;
返回null;
};
//TODO:在这里,您需要连接,因此连接存在
var cnx=GetProcessConnection(remoteEndPoint).FirstOrDefault();
//此处拒绝访问表示您没有足够的权限
cnx.DataStatsEnabled=true;
//TODO:在这里,您需要执行另一个请求,因此值会递增
//现在,你应该
static IEnumerable<TcpConnection> GetProcessConnection(IPEndPoint ep)
{
var p = Process.GetCurrentProcess();
return TcpConnection.GetAll().Where(c => ep.Equals(c.RemoteEndPoint) && c.ProcessId == p.Id);
}
HttpWebRequest req = ...
// this is how you can get the enpoint, or you can also built it by yourself manually
IPEndPoint remoteEndPoint;
req.ServicePoint.BindIPEndPointDelegate += (sp, rp, rc) =>
{
remoteEndPoint = rp;
return null;
};
// TODO: here, you need to connect, so the connection exists
var cnx = GetProcessConnection(remoteEndPoint).FirstOrDefault();
// access denied here means you don't have sufficient rights
cnx.DataStatsEnabled = true;
// TODO: here, you need to do another request, so the values are incremented
// now, you should get non-zero values here
// note TcpConnection also has int/out bandwidth usage, and in/out packet usage.
Console.WriteLine("DataBytesIn:" + cnx.DataBytesIn);
Console.WriteLine("DataBytesOut:" + cnx.DataBytesOut);
// if you need all connections in the current process, just do this
ulong totalBytesIn = 0;
ulong totalBytesOut = 0;
Process p = Process.GetCurrentProcess();
foreach (var cnx in TcpConnection.GetAll().Where(c => c.ProcessId == p.Id))
{
totalBytesIn += cnx.DataBytesIn;
totalBytesOut += cnx.DataBytesOut;
}
class Program
{
static void Main(string[] args)
{
ProcessTcpConnections p = new ProcessTcpConnections(Process.GetCurrentProcess().Id);
Timer timer = new Timer(UpdateStats, p, 0, 100);
do
{
// let's activate the network so we measure something...
using (WebClient client = new WebClient())
{
client.DownloadString("http://www.example.com");
}
Console.ReadKey(true); // press any key to download again
}
while (true);
}
private static void UpdateStats(object state)
{
ProcessTcpConnections p = (ProcessTcpConnections)state;
p.Update();
Console.WriteLine("DataBytesIn:" + p.DataBytesIn + " DataBytesOut:" + p.DataBytesOut);
}
}
public class ProcessTcpConnections : TcpConnectionGroup
{
public ProcessTcpConnections(int processId)
: base(c => c.ProcessId == processId)
{
ProcessId = processId;
}
public int ProcessId { get; private set; }
}
public class TcpConnectionGroup
{
private List<TcpConnectionStats> _states = new List<TcpConnectionStats>();
private Func<TcpConnection, bool> _groupFunc;
public TcpConnectionGroup(Func<TcpConnection, bool> groupFunc)
{
if (groupFunc == null)
throw new ArgumentNullException("groupFunc");
_groupFunc = groupFunc;
}
public void Update()
{
foreach (var conn in TcpConnection.GetAll().Where(_groupFunc))
{
if (!conn.DataStatsEnabled)
{
conn.DataStatsEnabled = true;
}
TcpConnectionStats existing = _states.Find(s => s.Equals(conn));
if (existing == null)
{
existing = new TcpConnectionStats();
_states.Add(existing);
}
existing.DataBytesIn = conn.DataBytesIn;
existing.DataBytesOut = conn.DataBytesOut;
existing.LocalEndPoint = conn.LocalEndPoint;
existing.RemoteEndPoint = conn.RemoteEndPoint;
existing.State = conn.State;
existing.LastUpdateTime = DateTime.Now;
}
}
public ulong DataBytesIn
{
get
{
ulong count = 0; foreach (var state in _states) count += state.DataBytesIn; return count;
}
}
public ulong DataBytesOut
{
get
{
ulong count = 0; foreach (var state in _states) count += state.DataBytesOut; return count;
}
}
private class TcpConnectionStats
{
public ulong DataBytesIn { get; set; }
public ulong DataBytesOut { get; set; }
public IPEndPoint LocalEndPoint { get; set; }
public IPEndPoint RemoteEndPoint { get; set; }
public TcpState State { get; set; }
public DateTime LastUpdateTime { get; set; }
public bool Equals(TcpConnection connection)
{
return LocalEndPoint.Equals(connection.LocalEndPoint) && RemoteEndPoint.Equals(connection.RemoteEndPoint);
}
}
}
using System;
using System.Diagnostics;
using System.Globalization;
using System.Text.RegularExpressions;
namespace NetworkTracing
{
/// <summary>
/// Description of NetworkListner.
/// </summary>
public class NetworkListner : TraceListener
{
public static int BytesSent { get; private set;}
public static int BytesReceived { get; private set;}
private bool _inSend = false;
private bool _inReceived = false;
private string _lastMessage = "";
private Regex _lengthRegex = new Regex(@"(\[\d*\]) ([\dA-F]*)");
public NetworkListner()
{
BytesSent = 0;
BytesReceived = 0;
}
private int ExtractNumOfBytes(string message){
string lengthUntilThisLineStr = null;
try {
var match = _lengthRegex.Match(message);
lengthUntilThisLineStr = match.Groups[2].Value;
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}
if (String.IsNullOrEmpty(lengthUntilThisLineStr)) {
return 0;
}
var lengthUntilThisLine = int.Parse(lengthUntilThisLineStr,NumberStyles.HexNumber);
return lengthUntilThisLine;
}
public override void Write(string message) {
if (message.Equals("System.Net.Sockets Verbose: 0 : ")) {
return;
}
if (message.Contains("Exiting Socket#")) {
int bytes = ExtractNumOfBytes(_lastMessage);
if (_inSend) {
_inSend = false;
BytesSent += bytes;
}else if (_inReceived) {
_inReceived = false;
BytesReceived += bytes;
}
}
else if (message.Contains("Data from Socket")){
if (message.Contains("Send")) {
_inSend = true;
}
else if (message.Contains("Receive")) {
_inReceived = true;
}
}
_lastMessage = message;
}
public override void WriteLine(string message) {
Write(message + Environment.NewLine);
}
}
}
using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net;
namespace NetworkTracing
{
class Program
{
public static void Main(string[] args)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.google.com");
request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0";
using (WebResponse response = request.GetResponse())
{
using (Stream strumien = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(strumien))
{
var res = sr.ReadToEnd();
Console.WriteLine("Send -> {0}",NetworkListner.BytesSent);
Console.WriteLine("Recieve -> {0}",NetworkListner.BytesReceived);
Console.ReadLine();
}
}
}
}
}
<configuration>
<system.diagnostics>
<sources>
<source name="System.Net.Sockets" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="network"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
<sharedListeners>
<add name="network"
type="NetworkTracing.NetworkListner, NetworkTracing"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
</configuration>
public class WebConnectionStats
{
static int _Read = 0;
static int _Written = 0;
public static void Init(bool registerAsSystemProxy = false)
{
Fiddler.FiddlerApplication.OnReadRequestBuffer += (s, e) => Interlocked.Add(ref _Written, e.iCountOfBytes);
Fiddler.FiddlerApplication.OnReadResponseBuffer += (s, e) => Interlocked.Add(ref _Read, e.iCountOfBytes);
Fiddler.FiddlerApplication.Startup(8088, registerAsSystemProxy, true);
}
public static int Read
{
get { return _Read; }
}
public static int Written
{
get { return _Written; }
}
}
WebConnectionStats.Init(); //call this only once
var client = HttpWebRequest.Create("http://stackoverflow.com") as HttpWebRequest;
client.Proxy = new WebProxy("127.0.0.1", 8088);
var resp = client.GetResponse();
var html = new StreamReader(resp.GetResponseStream()).ReadToEnd();
Console.WriteLine("Read: {0} Write: {1}", WebConnectionStats.Read,
WebConnectionStats.Written);
using System.Diagnostics;
using System.Linq;
public class NetworkMonitor
{
private PerformanceCounter _bytesSent;
private PerformanceCounter _bytesReceived;
private readonly int _processId;
private bool _initialized;
public NetworkMonitor(int processID)
{
_processId = processID;
Initialize();
}
public NetworkMonitor()
: this(Process.GetCurrentProcess().Id)
{
}
private void Initialize()
{
if (_initialized)
return;
var category = new PerformanceCounterCategory(".NET CLR Networking 4.0.0.0");
var instanceNames = category.GetInstanceNames().Where(i => i.Contains(string.Format("p{0}", _processId)));
if (!instanceNames.Any()) return;
_bytesSent = new PerformanceCounter
{
CategoryName = ".NET CLR Networking 4.0.0.0",
CounterName = "Bytes Sent",
InstanceName = instanceNames.First(),
ReadOnly = true
};
_bytesReceived = new PerformanceCounter
{
CategoryName = ".NET CLR Networking 4.0.0.0",
CounterName = "Bytes Received",
InstanceName = instanceNames.First(),
ReadOnly = true
};
_initialized = true;
}
public float GetSentBytes()
{
Initialize(); //in Net4.0 performance counter will get activated after first request
return _initialized ? _bytesSent.RawValue : 0;
}
enter code here
public float GetReceivedBytes()
{
Initialize(); //in Net4.0 performance counter will get activated after first request
return _initialized ? _bytesReceived.RawValue : 0;
}
}
<system.net>
<settings>
<performanceCounters enabled="true" />
</settings>
</system.net>
private static void Main(string[] args)
{
var netMonitor = new NetworkMonitor();
var received = netMonitor.GetReceivedBytes();
var sent = netMonitor.GetSentBytes();
Console.WriteLine("received:{0}, sent:{1}", received, sent);
func_fetch_Page("http://www.google.com");
received = netMonitor.GetReceivedBytes();
sent = netMonitor.GetSentBytes();
Console.WriteLine("received:{0}, sent:{1}", received, sent);
Console.ReadKey();
}