好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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测试数据pression;

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 "" ;

     }

   }

}

以上就是关于c# socket发送http/https请求的核心代码了,需要的朋友可以参考一下。

dy("nrwz");

查看更多关于c#使用Socket发送HTTP/HTTPS请求的实现代码的详细内容...

  阅读:65次