C# 使用TcpClient模拟HTTP请求的使用
一般做http模拟请求的一般使用HttpWebRequest这种方式,但这种方式也存在着一些bug,因为HttpWebRequest是使用的Windows系统定制的net通信,xp跟win7他们有的地方就不一样,HttpWebRequest可以说是给Windows定制的模拟操作,如果遇见某些服务器,可能根本不吃这一套,就像我最近遇到的问题,设置的Content-Length竟然可能视为无效,但正常访问抓包ok,程序跑起来有一半多时候会出错,还有其他的一些问题,比如设置了进制自动重定向,如果再设置Expect100Continue时候,前面的设置会发生无效,无奈,尝试使用TcpClient方式解决了。当下载文件时候,HttpWebRequest好像根据操作系统有最大文件的限制,所以这个时候使用TcpClient也是不错的选择
下面是我下好的一个类,我使用已经够了,可能中间有不足,希望大家指出
1 class HTTPClass 2 { 3 4 public Response HTTP(string _url, string _type, string _postdata, string _cookie, Encoding _responseEncode) 5 { 6 7 try 8 { 9 TcpClient clientSocket = new TcpClient(); 10 Uri URI = new Uri(_url); 11 clientSocket.Connect(URI.Host, URI.Port); 12 StringBuilder RequestHeaders = new StringBuilder(); 13 14 RequestHeaders.Append(_type + " " + URI.PathAndQuery + " HTTP/1.1\r\n"); 15 RequestHeaders.Append("Content-Type:application/x-www-form-urlencoded\r\n"); 16 RequestHeaders.Append("User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11\r\n"); 17 RequestHeaders.Append("Cookie:" + _cookie + "\r\n"); 18 RequestHeaders.Append("Accept:*/*\r\n"); 19 RequestHeaders.Append("Host:" + URI.Host + "\r\n"); 20 RequestHeaders.Append("Content-Length:" + _postdata.Length + "\r\n"); 21 RequestHeaders.Append("Connection:close\r\n\r\n"); 22 23 byte[] request = Encoding.UTF8.GetBytes(RequestHeaders.ToString() + _postdata); 24 clientSocket.Client.Send(request); 25 26 byte[] responseByte = new byte[1024000]; 27 int len = clientSocket.Client.Receive(responseByte); 28 string result = Encoding.UTF8.GetString(responseByte, 0, len); 29 clientSocket.Close(); 30 int headerIndex = result.IndexOf("\r\n\r\n"); 31 string[] headerStr = result.Substring(0, headerIndex).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 32 Dictionary responseHeader = new Dictionary(); 33 for (int i = 0; i < headerStr.Length; i++) 34 { 35 string[] temp = headerStr[i].Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries); 36 if (temp.Length == 2) 37 { 38 if (responseHeader.ContainsKey(temp[0])) 39 { 40 responseHeader[temp[0]] = temp[1]; 41 } 42 else 43 { 44 responseHeader.Add(temp[0], temp[1]); 45 } 46 } 47 } 48 Response response = new Response(); 49 response.HTTPResponseHeader = responseHeader; 50 string[] httpstatus = headerStr[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); 51 if (httpstatus.Length > 2) 52 { 53 54 response.HTTPStatusCode = httpstatus[1]; 55 } 56 else 57 { 58 59 response.HTTPStatusCode = "400"; 60 } 61 response.HTTPResponseText = _responseEncode.GetString(Encoding.UTF8.GetBytes(result.Substring(headerIndex + 4))); 62 return response; 63 64 } 65 catch 66 { 67 return null; 68 } 69 70 } 71 72 73 } 74 75 class Response 76 { 77 78 string hTTPStatusCode; 79 /// 80 81 /// http状态代码 82 /// 83 84 public string HTTPStatusCode 85 { 86 get { return hTTPStatusCode; } 87 set { hTTPStatusCode = value; } 88 } 89 Dictionary hTTPResponseHeader; 90 /// 91 92 /// Response的header 93 /// 94 95 public Dictionary HTTPResponseHeader 96 { 97 get { return hTTPResponseHeader; } 98 set { hTTPResponseHeader = value; } 99 } 100 string hTTPResponseText; 101 /// 102 103 /// html代码 104 /// 105 106 public string HTTPResponseText 107 { 108 get { return hTTPResponseText; } 109 set { hTTPResponseText = value; } 110 } 111 112 113 }
只给大家做参考使用,具体情况具体分析
以上程序对对于来获取一个小网页完全可以,但如果你网页比较大的话,就会出现接收不全的问题,这个问题主要是因为服务器那边响应请求的时候,首先把要响应的内容写如缓冲区,然后根据本身的设定一次次发送内容,而我这只是接受了一次,所以当文本过大时候,就会只接收一部分,如果你的内容过大,可以循环接收下来解决这个问题,当然,可能你有更好的方法
浙公网安备 33010602011771号