Http 代理工具 实战 支持网页与QQ代理

    xiaoxiao2022-07-09  202

    前言:

    有些公司不让员工上Q或封掉某些网站,这时候,干着急没办法,只能鄱墙。 如果上网搜代理IP,很少能用,用HTTP-Tunnel Client代理软件,免费的也是经常性的掉线。 正好手头上有N台服务器,如果直接在上面装个CCProxy,也显的太明显了。 于是自己写个代理软件放上去,一来包装一下好伪装,二来又有代理功能,看着挺好。

     

    原理解说:

    1:创建一个Socket进行本地端口监听-》一个死循环while语句 2:收到消息时,产生一个线程处理->多线程处理并发请求 3:产生一个新的Socket负责转发和接收 4:原来的Socket负责把新接收的消息发送回客户端

     

    代码细说

    说明:本次示例在控制台程序里运行。

     

    一:Program.cs

     

    1:简单函数原型

    using  System; using  System.Collections.Generic; using  System.Text; using  System.Diagnostics; using  System.Net.Sockets; using  System.Threading; namespace  TcpProxy {      ///   <summary>      ///  by 路过秋天      ///   http://www.cnblogs.com/cyq1162      ///   </summary>      class  Program     {                 static   void  Main( string [] args)         {                 Listen( 808 ); // 起始监听808和CCProxy一样。          }          static   void  Write( string  msg) // 简化消息输出         {             Console.WriteLine(msg);         }          static   void  Listen( int  port) // 开始监听          {                     }          static   void  ReListen(TcpListener listener) // 监听失败,需要重新换端口监听         {                     }     } }

     

    2:开始监听

            static   void  Listen( int  port) // 开始监听         {             Write( " 准备监听端口: "   +  port);             System.Net.IPAddress ipp  =  System.Net.IPAddress.Parse( " 0.0.0.0 " ); // 监听本地任意IP             TcpListener tcplistener  =   new  TcpListener(ipp, port);              // 端口复用,xp下可以复用[可抢占IIS80端口],win2003下无效。             tcplistener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress,  true );              try             {                 tcplistener.Start();             }              catch  (Exception err)             {                 Write(err.Message);                 Write( " 该端口已被占用,请更换端口号!!! " );                 ReListen(tcplistener); // 监听失败,切换端口监听             }              // 下面还有代码,暂时省略         }

     

    3:监听失败,切换端口监听

            static   void  ReListen(TcpListener listener) // 监听失败,需要重新换端口监听         {              if  (listener  !=   null )             {                 listener.Stop();                 listener  =   null ;             }             Write( " 请输入监听端口号: " );              string  newPort  =  Console.ReadLine();              int  port;              if  ( int .TryParse(newPort,  out  port))             {                 Listen(port);             }              else             {                 ReListen(listener);             }         }

     

    4:开始监听,进入死循环

            static   void  Listen( int  port) // 开始监听         {            // 上面代码省略......             Write( " 成功监听端口: "   +  port);             Socket socket;              while  ( true )             {               socket  =  tcplistener.AcceptSocket(); // 获取传送和接收数据的Scoket实例                  Proxy proxy  =   new  Proxy(socket); // Proxy类实例化                Thread thread  =   new  Thread( new  ThreadStart(proxy.Run)); // 创建线程                  thread.Start(); // 启动线程              }         }

     

    作者:路过秋天

    博客:http://cyq1162.cnblogs.com/

     

     

    二:Proxy.cs

     

    Proxy简单函数原型:

    using  System; using  System.Collections.Generic; using  System.Text; using  System.Net; using  System.Net.Sockets; using  System.IO; namespace  TcpProxy {      ///   <summary>      ///  by 路过秋天      ///   http://www.cnblogs.com/cyq1162      ///   </summary>      public   class  Proxy     {         Socket clientSocket; // 接收和返回          byte [] read  =   null ; // 存储来自客户端请求数据包          byte [] sendBytes  =   null ; // 存储中转请求发送的数据          byte [] recvBytes  =   null ; // 存储中转请求返回的数据          bool  isConnect  =   false ;          byte [] qqSendBytes = new   byte [ 4096 ]; // QQ发送缓冲          byte [] qqRecvBytes  =   new   byte [ 4096 ]; // QQ接收缓冲          int  sendLength  =   0 , recvLength  =   0 ; // 实际发送和接收长度          public  Proxy(Socket socket) // 初始化         {             clientSocket  =  socket;             recvBytes  =   new  Byte[ 1024   *   1024 ];             clientSocket.ReceiveBufferSize  =  recvBytes.Length;             clientSocket.SendBufferSize  =  recvBytes.Length;         }                   public   void  Run(){} // 主运行代码          // 从请求头里解析出url和端口号          private   string  GetUrl( string  clientmessage,  ref   int  port){}          // 接收客户端的HTTP请求数据          private   int  ReadMessage( byte [] readByte,  ref  Socket s,  ref  IPAddress ipAddress,  ref   string  host,  ref   int  port){}          // 关闭socket          private   void  CloseSocket(Socket socket){}          private   void  CloseSocket(Socket socket,  bool  shutdown){}          // QQ代理测试返回          private   byte [] QQokProxyData(){}          // firfox默认会发送一些请求,很烦,所以加过滤          private   bool  Filter( string  url){ }         private void Write(string msg)         {             System.Console.WriteLine(msg);         }     } }

     

    Run主函数

     

    A:分解请求头,获取要请求的IP,端口

                #region  获取客户端请求数据             Write( " -----------------------------请求开始--------------------------- " );             read  =   new   byte [clientSocket.Available];             IPAddress ipAddress  =  IPAddress.Any;              string  host  =   "" ; // 主机               int  port  =   80 ; // 端口               int  bytes  =  ReadMessage(read,  ref  clientSocket,  ref  ipAddress,  ref  host,  ref  port);              if  (bytes  ==   0 )             {                 Write( " 读取不到数据! " );                 CloseSocket(clientSocket);                  return ;             }              #endregion

     

    Run函数分解:ReadMessage函数

    ReadMessage函数

     

    ReadMessage函数分解:GetUrl

    GetUrl函数

     

    ReadMessage函数分解:Filter

    Filter函数         private   bool  Filter( string  url)         {              switch  (url.ToLower())             {                  case   " fffocus.cn " :                      return   true ;             }              return   false ;         }

     

    Run函数分解:CloseSocket函数

    CloseSocket函数

     

    B:创建中转Socket及建立连接

               #region  创建中转Socket及建立连接             IPEndPoint ipEndpoint  =   new  IPEndPoint(ipAddress, port);             Socket IPsocket  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);              try             {                 IPsocket.Connect(ipEndpoint); Write( " -----Socket 建立连接! IP地址: "   +  ipAddress  +   " 网址:http:// "   +  host);             }              catch  (Exception err)             {                 Write( " 连接失败 : "   +  err.Message);                 Write( " 退出请求!!! " );                 CloseSocket(IPsocket,  false );                  return ;             }                #endregion

     

     

    C:QQ代理测试及网页转发

                 if  (isConnect) // QQ链接方式             {                  byte [] qqOkData  =  QQokProxyData();                 clientSocket.Send(qqOkData,  0 , qqOkData.Length,  0 );             }              else // 正常网页,直接转发             {                 IPsocket.Send(sendBytes,  0 );             }

     

    函数分解:QQokProxyData

             private   byte [] QQokProxyData()         {              string  data  =   " HTTP/1.0 200 Connection established " ; // 返回建立成功";              return  System.Text.Encoding.ASCII.GetBytes(data);         }

     

    D:针对QQ需要进行重复来回的发送与接收

    QQ转发处理

     

    E:结束请求,关闭客户端Socket

                 #region  结束请求,关闭客户端Socket             Write( " 接收完成。返回客户端数据... "   +  count);             CloseSocket(IPsocket);             CloseSocket(clientSocket);             recvBytes  =   null ;             Write( " 本次请求完成,已关闭连接... " );             Write( " -----------------------------请求结束--------------------------- " );              #endregion

     

    结言:

    本QQ代理软件在服务器上运行长达三个多月,使用过程未发现异常退出情况。当然前提就我一个人在用了 ~ 哈哈 ~

     

     

    附以前写的几篇文章:

    1:简单实现Http代理工具

    2:简单实现Http代理工具--端口复用与QQ代理

    3:简单实现Http代理工具--完善支持QQ代理

    4:C# 控制台程序 不显示在任务栏 只在进程中显示

     

    看本篇的时候也请支持一下我的开源框架:CYQ.Data 轻量数据层之路 框架开源系列 索引

    版权声明:本文原创发表于博客园,作者为路过秋天,原文链接:

    http://www.cnblogs.com/cyq1162/archive/2010/09/21/1832329.html

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)