1、1using System;using System.Collections.Generic;using System.Text;using System.Net;using System.Net.Sockets;using System.Collections;using System.IO;using System.Text.RegularExpressions;using RE = System.Text.RegularExpressions.Regex;using System.Security.Cryptography.X509Certificates;/* *文件名:HttpPro
2、c.cs* *创建人:HeDaode* *日 期:2007.09.01* *描 述:实现 HTTP 协议中的 GET、POST 请求* *使 用:HttpProc.WebClient client = new HttpProc.WebClient();client.Encoding = System.Text.Encoding.Default;/默认编码方式,根据需要设置其他类型client.OpenRead(“http:/“);/普通 get 请求MessageBox.Show(client.RespHtml);/获取返回的网页源代码client.DownloadFile(“http:/ “
3、file1=D:1.mp3“);/上传文件client.UploadFile(“http:/ “folder=myfolder/提交含文本域和文件域的表单*/namespace HttpProc/上传事件委托/public delegate void WebClientUploadEvent(object sender, HttpProc.UploadEventArgs e);/下载事件委托/public delegate void WebClientDownloadEvent(object sender, HttpProc.DownloadEventArgs e);/上传事件参数/publi
4、c struct UploadEventArgs/上传数据总大小/public long totalBytes;/已发数据大小/public long bytesSent;/发送进度(0-1)/public double sendProgress;/发送速度 Bytes/s/public double sendSpeed;/下载事件参数/public struct DownloadEventArgs/下载数据总大小/public long totalBytes;/已接收数据大小/public long bytesReceived;/接收数据进度(0-1)/public double Recei
5、veProgress;/当前缓冲区数据/public byte receivedBuffer;/接收速度 Bytes/s/public double receiveSpeed;/实现向 WEB 服务器发送和接收数据/public class WebClientprivate WebHeaderCollection requestHeaders, responseHeaders;private TcpClient clientSocket;private MemoryStream postStream;private Encoding encoding = Encoding.Default;pr
6、ivate const string BOUNDARY = “-HEDAODE-“;private const int SEND_BUFFER_SIZE = 10245;private const int RECEIVE_BUFFER_SIZE = 10245;private string cookie = “;private string respHtml = “;private string strRequestHeaders = “;private string strResponseHeaders = “;private int statusCode = 0;private bool
7、isCanceled = false;public event WebClientUploadEvent UploadProgressChanged;public event WebClientDownloadEvent DownloadProgressChanged;/初始化 WebClient 类/public WebClient()responseHeaders = new WebHeaderCollection();requestHeaders = new WebHeaderCollection();/读取指定 URL 的文本/请求的地址 /服务器响应文本public string O
8、penRead(string URL)requestHeaders.Add(“Connection“, “close“);SendRequestData(URL, “GET“);return GetHtml();/解决证书过期无法访问的问题class CertPolicy : ICertificatePolicypublic bool CheckValidationResult(ServicePoint srvpt, X509Certificate cert, WebRequest req, int certprb) return true; /采用 https 协议访问网络/url 地址/发
9、送的数据/public string OpenReadWithHttps(string URL,string strPostdata)ServicePointManager.CertificatePolicy = new CertPolicy();HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);request.CookieContainer = new CookieContainer();request.Method = “POST“;request.Accept = “*/*“;request.ContentTy
10、pe=“application/x-www-form-urlencoded“;byte buffer = this.encoding.GetBytes(strPostdata);request.ContentLength = buffer.Length;request.GetRequestStream().Write(buffer, 0, buffer.Length);HttpWebResponse response = (HttpWebResponse)request.GetResponse();StreamReader reader = new StreamReader(response.
11、GetResponseStream(), encoding);this.respHtml = reader.ReadToEnd();foreach (System.Net.Cookie ck in response.Cookies)this.cookie += ck.Name + “=“ + ck.Value + “;“;reader.Close();return respHtml;/读取指定 URL 的文本/请求的地址 /向服务器发送的文本数据/服务器响应文本public string OpenRead(string URL, string postData)byte sendBytes =
12、 encoding.GetBytes(postData);postStream = new MemoryStream();postStream.Write(sendBytes, 0, sendBytes.Length);requestHeaders.Add(“Content-Length“, postStream.Length.ToString();requestHeaders.Add(“Content-Type“, “application/x-www-form-urlencoded“);requestHeaders.Add(“Connection“, “close“);SendReques
13、tData(URL, “POST“);return GetHtml();/读取指定 URL 的流/请求的地址 /向服务器发送的数据/服务器响应流public Stream GetStream(string URL, string postData)byte sendBytes = encoding.GetBytes(postData);postStream = new MemoryStream();postStream.Write(sendBytes, 0, sendBytes.Length);requestHeaders.Add(“Content-Length“, postStream.Le
14、ngth.ToString();requestHeaders.Add(“Content-Type“, “application/x-www-form-urlencoded“);requestHeaders.Add(“Connection“, “close“);SendRequestData(URL, “POST“);MemoryStream ms = new MemoryStream();SaveNetworkStream(ms);return ms;/上传文件到服务器/请求的地址 /文件域(格式如:file1=C:test.mp3/上传文件和数据到服务器/请求地址 /文本域(格式为:name
15、1=value1if (textField != “ WriteFileField(fileField);else if (fileField != “)WriteFileField(fileField);else if (textField != “)WriteTextField(textField);elsethrow new Exception(“文本域和文件域不能同时为空。“);/写入结束标记byte buffer = encoding.GetBytes(“-“ + BOUNDARY + “-rn“);postStream.Write(buffer, 0, buffer.Length)
16、;/添加请求标头requestHeaders.Add(“Content-Length“, postStream.Length.ToString();requestHeaders.Add(“Content-Type“, “multipart/form-data; boundary=“ + BOUNDARY);requestHeaders.Add(“Connection“, “Keep-Alive“);/发送请求数据SendRequestData(URL, “POST“, true);/返回响应文本return GetHtml();/分析文本域,添加到请求流/文本域private void Wri
17、teTextField(string textField)string strArr = RE.Split(textField, “textField = “;foreach (string var in strArr)Match M = RE.Match(var, “(=+)=(.+)“);textField += “-“ + BOUNDARY + “rn“;textField += “Content-Disposition: form-data; name=“ + M.Groups1.Value + “rnrn“ + M.Groups2.Value + “rn“;byte buffer =
18、 encoding.GetBytes(textField);postStream.Write(buffer, 0, buffer.Length);/分析文件域,添加到请求流/文件域private void WriteFileField(string fileField)string filePath = “;int count = 0;string strArr = RE.Split(fileField, “foreach (string var in strArr)Match M = RE.Match(var, “(=+)=(.+)“);filePath = M.Groups2.Value;
19、fileField = “-“ + BOUNDARY + “rn“;fileField += “Content-Disposition: form-data; name=“ + M.Groups1.Value + “; filename=“ + Path.GetFileName(filePath) + “rn“;fileField += “Content-Type: image/jpegrnrn“;byte buffer = encoding.GetBytes(fileField);postStream.Write(buffer, 0, buffer.Length);/添加文件数据FileSt
20、ream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);buffer = new byte50000;docount = fs.Read(buffer, 0, buffer.Length);postStream.Write(buffer, 0, count); while (count 0);fs.Close();fs.Dispose();fs = null;buffer = encoding.GetBytes(“rn“);postStream.Write(buffer, 0, buffer.Length);/从指定
21、 URL 下载数据流/请求地址 /数据流public Stream DownloadData(string URL)requestHeaders.Add(“Connection“, “close“);SendRequestData(URL, “GET“);MemoryStream ms = new MemoryStream();SaveNetworkStream(ms, true);return ms;/从指定 URL 下载文件/文件 URL 地址/文件保存路径,含文件名(如:C:test.jpg)public void DownloadFile(string URL, string file
22、Name)requestHeaders.Add(“Connection“, “close“);SendRequestData(URL, “GET“);FileStream fs = new FileStream(fileName, FileMode.Create);SaveNetworkStream(fs, true);fs.Close();fs = null;/向服务器发送请求/请求地址 /POST 或 GET/是否显示上传进度private void SendRequestData(string URL, string method, bool showProgress)clientSoc
23、ket = new TcpClient();Uri URI = new Uri(URL);clientSocket.Connect(URI.Host, URI.Port);requestHeaders.Add(“Host“, URI.Host);byte request = GetRequestHeaders(method + “ “ + URI.PathAndQuery + “ HTTP/1.1“);clientSocket.Client.Send(request);/若有实体内容就发送它if (postStream != null)byte buffer = new byteSEND_BU
24、FFER_SIZE;int count = 0;Stream sm = clientSocket.GetStream();postStream.Position = 0;UploadEventArgs e = new UploadEventArgs();e.totalBytes = postStream.Length;System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();/计时器timer.Start();do/如果取消就推出if (isCanceled) break; /读取要发送的数据count =
25、postStream.Read(buffer, 0, buffer.Length);/发送到服务器sm.Write(buffer, 0, count);/是否显示进度if (showProgress)/触发事件e.bytesSent += count;e.sendProgress = (double)e.bytesSent / (double)e.totalBytes;double t = timer.ElapsedMilliseconds / 1000;t = t 0);timer.Stop();postStream.Close();/postStream.Dispose();postStr
26、eam = null;/end if/向服务器发送请求/请求 URL 地址/POST 或 GETprivate void SendRequestData(string URL, string method)SendRequestData(URL, method, false);/获取请求头字节数组/POST 或 GET 请求/请求头字节数组private byte GetRequestHeaders(string request)requestHeaders.Add(“Accept“, “*/*“);requestHeaders.Add(“Accept-Language“, “zh-cn“);
27、requestHeaders.Add(“User-Agent“, “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)“);string headers = request + “rn“;foreach (string key in requestHeaders)headers += key + “:“ + requestHeaderskey + “rn“;/有 Cookie 就带上 Cookieif (cookie != “) headers += “Co
28、okie:“ + cookie + “rn“; /空行,请求头结束headers += “rn“;strRequestHeaders = headers;requestHeaders.Clear();return encoding.GetBytes(headers);/获取服务器响应文本/服务器响应文本private string GetHtml()MemoryStream ms = new MemoryStream();SaveNetworkStream(ms);/将网络流保存到内存流StreamReader sr = new StreamReader(ms, encoding);respH
29、tml = sr.ReadToEnd();sr.Close(); ms.Close();return respHtml;/将网络流保存到指定流/保存位置/是否显示进度private void SaveNetworkStream(Stream toStream, bool showProgress)/获取要保存的网络流NetworkStream NetStream = clientSocket.GetStream();byte buffer = new byteRECEIVE_BUFFER_SIZE;int count = 0, startIndex = 0;MemoryStream ms =
30、new MemoryStream();for (int i = 0; i 0);timer.Stop();/关闭计时器if (responseHeaders“Content-Length“ != null)toStream.SetLength(long.Parse(responseHeaders“Content-Length“);/else/ toStream.SetLength(toStream.Length);/ responseHeaders.Add(“Content-Length“, toStream.Length.ToString();/添加响应标头/toStream.Positio
31、n = 0;/关闭网络流和网络连接NetStream.Close();clientSocket.Close();/将网络流保存到指定流/保存位置private void SaveNetworkStream(Stream toStream)SaveNetworkStream(toStream, false);/分析响应流,去掉响应头/private void GetResponseHeader(byte buffer, out int startIndex)responseHeaders.Clear();string html = encoding.GetString(buffer);Strin
32、gReader sr = new StringReader(html);int start = html.IndexOf(“rnrn“) + 4;/找到空行位置strResponseHeaders = html.Substring(0, start);/获取响应头文本/获取响应状态码/if (sr.Peek() -1)/读第一行字符串string line = sr.ReadLine();/分析此行字符串,获取服务器响应状态码Match M = RE.Match(line, “ddd“);if (M.Success)statusCode = int.Parse(M.Value);/获取响应头/
33、while (sr.Peek() -1)/读一行字符串string line = sr.ReadLine();/若非空行if (line != “)/分析此行字符串,获取响应标头Match M = RE.Match(line, “(:+):(.+)“);if (M.Success)try /添加响应标头到集合responseHeaders.Add(M.Groups1.Value.Trim(), M.Groups2.Value.Trim();catch /获取 Cookieif (M.Groups1.Value = “Set-Cookie“)M = RE.Match(M.Groups2.Valu
34、e, “=+=;+“);cookie += M.Value.Trim() + “;“;/若是空行,代表响应头结束响应实体开始。 (响应头和响应实体间用一空行隔开)else/如果响应头中没有实体大小标头,尝试读响应实体第一行获取实体大小if (responseHeaders“Content-Length“ = null /分析此行看是否包含实体大小Match M = RE.Match(line, “0-9a-fA-F1,15“);if (M.Success)/将 16 进制的实体大小字符串转换为 10 进制int length = int.Parse(M.Value, System.Global
35、ization.NumberStyles.AllowHexSpecifier);responseHeaders.Add(“Content-Length“, length.ToString();/添加响应标头strResponseHeaders += M.Value + “rn“;break;/跳出循环 /End If/End Whilesr.Close();/实体开始索引startIndex = encoding.GetBytes(strResponseHeaders).Length;/取消上传或下载,要继续开始请调用 Start 方法/public void Cancel()isCancel
36、ed = true;/启动上传或下载,要取消请调用 Cancel 方法/public void Start()isCanceled = false;/*/以下为属性/*/获取或设置请求头/public WebHeaderCollection RequestHeadersset requestHeaders = value; get return requestHeaders; /获取响应头集合/public WebHeaderCollection ResponseHeadersget return responseHeaders; /获取请求头文本/public string StrReque
37、stHeadersget return strRequestHeaders; /获取响应头文本/public string StrResponseHeadersget return strResponseHeaders; /获取或设置 Cookie/public string Cookieset cookie = value; get return cookie; /获取或设置编码方式(默认为系统默认编码方式 )/public Encoding Encodingset encoding = value; get return encoding; /获取服务器响应文本/public string RespHtmlget return respHtml; /获取服务器响应状态码/public int StatusCodeget return statusCode;