这篇文章主要介绍了c#使用Socket发送HTTP/HTTPS请求的实现代码,需要的朋友可以参考下

C# 自带的HttpWebRequest效率太低,对于自组HTTP封包不好操作。

在写超级SQL注入工具时,研究了很长一段时间如何使用Socket来发送HTTP、HTTPS请求。

经过一年的修改和测试,可完美、高效发送并解析HTTP/HTTPS请求。修改过无数次bug。

在这里把核心代码分享出来,供大家学习或做开发参考。

用这个代码写了一个简单的HTTP发包工具。供大家参考。

工具下载:

HTTPTool.rar

核心类:HTTP.cs


using System;using System.Collections.Generic;using System.Text;using tools;using System.Net;using System.Net.Sockets;using System.IO.Compression;using System.IO;using System.Net.Security;using System.Text.RegularExpressions;using System.Threading;using System.Diagnostics;using System.Security.Authentication;using System.Security.Cryptography.X509Certificates;using HTTPTool; namespace tools{  public class HTTP  {    public const char T = '';    public const String CT = "";    public const String CTRL = " ";    public const String Content_Length_Str = "content-length: ";    public const String Content_Length_Str_M = "Content-Length: ";    public const String Content_Length = "content-length";    public const String Content_Encoding = "content-encoding";    public const String Transfer_Encoding = "transfer-encoding";    public const String Connection = "connection";    public static Main main = null;    public static long index = 0;    public void initMain(Main m)    {      main = m;    }     /**     *      发生异常尝试重连      *     */    public static ServerInfo sendRequestRetry(Boolean isSSL, int tryCount, String host, int port, String payload, String request, int timeout, String encoding, Boolean foward_302)    {      int count = 0;      Interlocked.Increment(ref index);      ServerInfo server = new ServerInfo();      timeout = timeout * 1000;      while (true)      {        if (count >= tryCount) break;         try        {          if (!isSSL)          {            server = sendHTTPRequest(count, host, port, payload, request, timeout, encoding, foward_302);            return server;          }          else          {             server = sendHTTPSRequest(count, host, port, payload, request, timeout, encoding, foward_302);            return server;           }        }        catch (Exception e)        {          Tools.SysLog("发包发生异常,正在重试----" + e.Message);          server.timeout = true;          continue;        }        finally        {          count++;        }       }      return server;     }     private static void checkContentLength(ref ServerInfo server, ref String request)    {       //重新计算并设置Content-length      int sindex = request.IndexOf(CTRL);      server.reuqestHeader = request;      if (sindex != -1)      {        server.reuqestHeader = request.Substring(0, sindex);        server.reuqestBody = request.Substring(sindex + 4, request.Length - sindex - 4);        int contentLength = Encoding.UTF8.GetBytes(server.reuqestBody).Length;        String newContentLength = Content_Length_Str_M + contentLength;         if (request.IndexOf(Content_Length_Str_M) != -1)        {          request = Regex.Replace(request, Content_Length_Str_M + "d+", newContentLength);        }        else        {          request = request.Insert(sindex, "" + newContentLength);        }      }      else      {        request = Regex.Replace(request, Content_Length_Str + "d+", Content_Length_Str_M + "0");        request += CTRL;      }      }     private static void doHeader(ref ServerInfo server, ref String[] headers)    {       for (int i = 0; i < headers.Length; i++)      {        if (i == 0)        {           server.code = Tools.convertToInt(headers[i].Split(' ')[1]);         }        else        {          String[] kv = Regex.Split(headers[i], ": ");          String key = kv[0].ToLower();          if (!server.headers.ContainsKey(key))          {            //自动识别编码            if ("content-type".Equals(key))            {              String hecnode = getHTMLEncoding(kv[1], "");              if (!String.IsNullOrEmpty(hecnode))              {                server.encoding = hecnode;              }            }            if (kv.Length > 1)            {              server.headers.Add(key, kv[1]);            }            else            {              server.headers.Add(key, "");            }          }        }      }     }      private static ServerInfo sendHTTPRequest(int count, String host, int port, String payload, String request, int timeout, String encoding, Boolean foward_302)    {       String index = Thread.CurrentThread.Name + HTTP.index;      Stopwatch sw = new Stopwatch();      sw.Start();      ServerInfo server = new ServerInfo();      TcpClient clientSocket = null;      int sum = 0;      try      {        if (port > 0 && port <= 65556)        {          //编码处理          server.request = request;          TimeOutSocket tos = new TimeOutSocket();          clientSocket = tos.Connect(host, port, timeout);          if (sw.ElapsedMilliseconds >= timeout)          {            return server;          }          clientSocket.SendTimeout = timeout - tos.useTime;          if (clientSocket.Connected)          {            checkContentLength(ref server, ref request);            server.request = request;             byte[] requestByte = Encoding.UTF8.GetBytes(request);            clientSocket.Client.Send(requestByte);            byte[] responseBody = new byte[1024 * 1000];            int len = 0;            //获取header头            String tmp = "";            StringBuilder sb = new StringBuilder();            clientSocket.ReceiveTimeout = timeout - (int)sw.ElapsedMilliseconds;            do            {              byte[] responseHeader = new byte[1];              len = clientSocket.Client.Receive(responseHeader, 1, SocketFlags.None);              if (len == 1)              {                 char c = (char)responseHeader[0];                sb.Append(c);                if (c.Equals(T))                {                  tmp = String.Concat(sb[sb.Length - 4], sb[sb.Length - 3], sb[sb.Length - 2], c);                }              }            } while (!tmp.Equals(CTRL) && sw.ElapsedMilliseconds < timeout);             server.header = sb.ToString().Replace(CTRL, "");            String[] headers = Regex.Split(server.header, CT);            if (headers != null && headers.Length > 0)            {              //处理header              doHeader(ref server, ref headers);              //自动修正编码              if (!String.IsNullOrEmpty(server.encoding))              {                encoding = server.encoding;              }              Encoding encod = Encoding.GetEncoding(encoding);               //302 301跳转              if ((server.code == 302 || server.code == 301) && foward_302)              {                StringBuilder rsb = new StringBuilder(server.request);                int urlStart = server.request.IndexOf(" ") + 1;                int urlEnd = server.request.IndexOf(" HTTP");                if (urlStart != -1 && urlEnd != -1)                {                  String url = server.request.Substring(urlStart, urlEnd - urlStart);                  rsb.Remove(urlStart, url.Length);                  String location = server.headers["location"];                  if (!server.headers["location"].StartsWith("/") && !server.headers["location"].StartsWith("http"))                  {                    location = Tools.getCurrentPath(url) + location;                  }                  rsb.Insert(urlStart, location);                   return sendHTTPRequest(count, host, port, payload, rsb.ToString(), timeout, encoding, false);                }               }                //根据请求头解析              if (server.headers.ContainsKey(Content_Length))              {                int length = int.Parse(server.headers[Content_Length]);                 while (sum < length && sw.ElapsedMilliseconds < timeout)                {                  int readsize = length - sum;                  len = clientSocket.Client.Receive(responseBody, sum, readsize, SocketFlags.None);                  if (len > 0)                  {                    sum += len;                  }                }              }              //解析chunked传输              else if (server.headers.ContainsKey(Transfer_Encoding))              {                //读取长度                int chunkedSize = 0;                byte[] chunkedByte = new byte[1];                //读取总长度                sum = 0;                do                {                  String ctmp = "";                  do                  {                    len = clientSocket.Client.Receive(chunkedByte, 1, SocketFlags.None);                    ctmp += Encoding.UTF8.GetString(chunkedByte);                   } while ((ctmp.IndexOf(CT) == -1) && (sw.ElapsedMilliseconds < timeout));                   chunkedSize = Tools.convertToIntBy16(ctmp.Replace(CT, ""));                   //chunked的结束0 是结束标志,单个chunked块结束                  if (ctmp.Equals(CT))                  {                    continue;                  }                  if (chunkedSize == 0)                  {                    //结束了                    break;                  }                  int onechunkLen = 0;                  while (onechunkLen < chunkedSize && sw.ElapsedMilliseconds < timeout)                  {                    len = clientSocket.Client.Receive(responseBody, sum, chunkedSize - onechunkLen, SocketFlags.None);                    if (len > 0)                    {                      onechunkLen += len;                      sum += len;                    }                  }                   //判断                } while (sw.ElapsedMilliseconds < timeout);              }              //connection close方式或未知body长度              else              {                while (sw.ElapsedMilliseconds < timeout)                {                  if (clientSocket.Client.Poll(timeout, SelectMode.SelectRead))                  {                    if (clientSocket.Available > 0)                    {                      len = clientSocket.Client.Receive(responseBody, sum, (1024 * 200) - sum, SocketFlags.None);                      if (len > 0)                      {                        sum += len;                      }                    }                    else                    {                      break;                    }                  }                }              }              //判断是否gzip              if (server.headers.ContainsKey(Content_Encoding))              {                server.body = unGzip(responseBody, sum, encod);              }              else              {                server.body = encod.GetString(responseBody, 0, sum);              }              }          }         }      }      catch (Exception e)      {        Exception ee = new Exception("HTTP发包错误!错误消息:" + e.Message + e.TargetSite.Name + "----发包编号:" + index);        throw ee;      }      finally      {        sw.Stop();        server.length = sum;        server.runTime = (int)sw.ElapsedMilliseconds;        if (clientSocket != null)        {          clientSocket.Close();        }      }      return server;     }     private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)    {      return true;    }    private static ServerInfo sendHTTPSRequest(int count, String host, int port, String payload, String request, int timeout, String encoding, Boolean foward_302)    {      String index = Thread.CurrentThread.Name + HTTP.index;      Stopwatch sw = new Stopwatch();      sw.Start();      ServerInfo server = new ServerInfo();       int sum = 0;       TcpClient clientSocket = null; ;       try      {         if (port > 0 && port <= 65556)        {           TimeOutSocket tos = new TimeOutSocket();          clientSocket = tos.Connect(host, port, timeout);          if (sw.ElapsedMilliseconds >= timeout)          {            return server;          }          clientSocket.SendTimeout = timeout - tos.useTime;           SslStream ssl = null;          if (clientSocket.Connected)          {            ssl = new SslStream(clientSocket.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate));            SslProtocols protocol = SslProtocols.Ssl3 | SslProtocols.Ssl2 | SslProtocols.Tls;            ssl.AuthenticateAsClient(host, null, protocol, false);            if (ssl.IsAuthenticated)            {              checkContentLength(ref server, ref request);              server.request = request;              byte[] requestByte = Encoding.UTF8.GetBytes(request);              ssl.Write(requestByte);              ssl.Flush();            }          }          server.request = request;          byte[] responseBody = new byte[1024 * 1000];          int len = 0;          //获取header头          String tmp = "";           StringBuilder sb = new StringBuilder();          StringBuilder bulider = new StringBuilder();          clientSocket.ReceiveTimeout = timeout - (int)sw.ElapsedMilliseconds;          do          {            byte[] responseHeader = new byte[1];            int read = ssl.ReadByte();             char c = (char)read;            sb.Append(c);            if (c.Equals(T))            {              tmp = String.Concat(sb[sb.Length - 4], sb[sb.Length - 3], sb[sb.Length - 2], c);            }           } while (!tmp.Equals(CTRL) && sw.ElapsedMilliseconds < timeout);           server.header = sb.ToString().Replace(CTRL, "");          String[] headers = Regex.Split(server.header, CT);          //处理header          doHeader(ref server, ref headers);          //自动修正编码          if (!String.IsNullOrEmpty(server.encoding))          {            encoding = server.encoding;          }          Encoding encod = Encoding.GetEncoding(encoding);          //302 301跳转          if ((server.code == 302 || server.code == 301) && foward_302)          {             int urlStart = server.request.IndexOf(" ");            int urlEnd = server.request.IndexOf(" HTTP");            if (urlStart != -1 && urlEnd != -1)            {              String url = server.request.Substring(urlStart + 1, urlEnd - urlStart - 1);              if (!server.headers["location"].StartsWith("/") && !server.headers["location"].StartsWith("https"))              {                server.request = server.request.Replace(url, Tools.getCurrentPath(url) + server.headers["location"]);              }              else              {                server.request = server.request.Replace(url, server.headers["location"]);              }               return sendHTTPSRequest(count, host, port, payload, server.request, timeout, encoding, false);            }           }            //根据请求头解析          if (server.headers.ContainsKey(Content_Length))          {            int length = int.Parse(server.headers[Content_Length]);            while (sum < length && sw.ElapsedMilliseconds < timeout)            {              len = ssl.Read(responseBody, sum, length - sum);              if (len > 0)              {                sum += len;              }            }          }          //解析chunked传输          else if (server.headers.ContainsKey(Transfer_Encoding))          {            //读取长度            int chunkedSize = 0;            byte[] chunkedByte = new byte[1];            //读取总长度            sum = 0;            do            {              String ctmp = "";              do              {                len = ssl.Read(chunkedByte, 0, 1);                ctmp += Encoding.UTF8.GetString(chunkedByte);               } while (ctmp.IndexOf(CT) == -1 && sw.ElapsedMilliseconds < timeout);               chunkedSize = Tools.convertToIntBy16(ctmp.Replace(CT, ""));               //chunked的结束0 是结束标志,单个chunked块结束              if (ctmp.Equals(CT))              {                continue;              }              if (chunkedSize == 0)              {                //结束了                break;              }              int onechunkLen = 0;               while (onechunkLen < chunkedSize && sw.ElapsedMilliseconds < timeout)              {                len = ssl.Read(responseBody, sum, chunkedSize - onechunkLen);                if (len > 0)                {                  onechunkLen += len;                  sum += len;                }              }               //判断            } while (sw.ElapsedMilliseconds < timeout);          }          //connection close方式或未知body长度          else          {            while (sw.ElapsedMilliseconds < timeout)            {              if (clientSocket.Client.Poll(timeout, SelectMode.SelectRead))              {                if (clientSocket.Available > 0)                {                  len = ssl.Read(responseBody, sum, (1024 * 200) - sum);                  if (len > 0)                  {                    sum += len;                  }                }                else                {                  break;                }              }            }          }          //判断是否gzip          if (server.headers.ContainsKey(Content_Encoding))          {            server.body = unGzip(responseBody, sum, encod);          }          else          {            server.body = encod.GetString(responseBody, 0, sum);          }        }       }      catch (Exception e)      {        Exception ee = new Exception("HTTPS发包错误!错误消息:" + e.Message + "----发包编号:" + index);        throw ee;      }      finally      {        sw.Stop();        server.length = sum;        server.runTime = (int)sw.ElapsedMilliseconds;         if (clientSocket != null)        {          clientSocket.Close();        }      }      return server;     }     public static String unGzip(byte[] data, int len, Encoding encoding)    {       String str = "";      MemoryStream ms = new MemoryStream(data, 0, len);      GZipStream gs = new GZipStream(ms, CompressionMode.Decompress);      MemoryStream outbuf = new MemoryStream();      byte[] block = new byte[1024];       try      {         while (true)        {          int bytesRead = gs.Read(block, 0, block.Length);          if (bytesRead <= 0)          {            break;          }          else          {            outbuf.Write(block, 0, bytesRead);          }        }        str = encoding.GetString(outbuf.ToArray());      }      catch (Exception e)      {        Tools.SysLog("解压Gzip发生异常----" + e.Message);      }      finally      {        outbuf.Close();        gs.Close();        ms.Close();       }      return str;     }    public static String getHTMLEncoding(String header, String body)    {      if (String.IsNullOrEmpty(header) && String.IsNullOrEmpty(body))      {        return "";      }      body = body.ToUpper();      Match m = Regex.Match(header, @"charsets*=s*""?(?<charset>[^""]*)", RegexOptions.IgnoreCase);      if (m.Success)      {        return m.Groups["charset"].Value.ToUpper();      }      else      {        if (String.IsNullOrEmpty(body))        {          return "";        }        m = Regex.Match(body, @"charsets*=s*""?(?<charset>[^""]*)", RegexOptions.IgnoreCase);        if (m.Success)        {          return m.Groups["charset"].Value.ToUpper();        }      }      return "";    }  }}

更多相关文章

  1. C# ArrayListd的长度问题解决
  2. c语句以句号结束对吗
  3. c语言字符串结束标志是什么
  4. c语言每条语句以什么结束
  5. 在什么语言中字符串以\0标志字符串的结束?
  6. C语言怎么获取数组的长度
  7. 在c语言中,一条简单语句的结束符为什么?
  8. 一个c程序的执行是从什么开始到什么结束
  9. c程序的执行是从什么开始到什么结束?

随机推荐

  1. SQL锁死解决办法
  2. 【Web安全与防御】简析Sql注入与防御措施
  3. 个人网站对xss跨站脚本攻击(重点是富文本
  4. MySQL 5.6 插入缓冲测试
  5. 从数据库sql中删除一个单词
  6. mysql常用命令/语句学习三
  7. MySQL忘记密码破解密码的方法
  8. mysql 执行计划和慢日志记录
  9. mysql数据库之表的操作
  10. Django查询优化:根据多对一到多对多查找对