简单实现Http代理工具

本来意图是想写个工具放到服务器里代理一下上秋秋的。

没想到N台(电信/联通/移动)的服务器都把端口全封了。

所以以下代码是在本地测试代理网页访问通过。

 

说下思路再上代码及下载:

其实一句话就是:产生两个Soket,一个负责接收请求和回发请求,另一个负责中转的去请求和接收。

重点一句话就是:每个请求产生一个线程处理,处理时关键是的延时处理(不然数据接收不全)。

 

现在上代码,Proxy自定义类:

 

Proxy
using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Net;
using  System.Net.Sockets;
using  System.IO;
//by 路过秋天
namespace  TCPProxy
{
    
public   class  Proxy
    {
        Socket clientSocket;
// 接收和返回
        Byte[] read  =   null ; // 存储来自客户端请求数据包
        Byte[] recvBytes  =   null ; // 存储中转请求返回的数据

        
public  Proxy(Socket socket)
        {
            clientSocket 
=  socket;
            recvBytes 
=   new  Byte[ 1024   *   1024 ];
            clientSocket.ReceiveBufferSize 
=  recvBytes.Length;
            clientSocket.SendBufferSize 
=  recvBytes.Length;
            clientSocket.SendTimeout 
=   10000 ;
            clientSocket.ReceiveTimeout 
=   10000 ;
        }
        
public   void  Run()
        {
            
#region  获取客户端请求数据
            
string  clientmessage  =   "" ;
            read 
=   new   byte [clientSocket.Available];
            
int  bytes  =  ReadMessage(read,  ref  clientSocket,  ref  clientmessage);
            
if  (bytes  ==   0 )
            {
                Write(
" 读取不到数据! " );
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
                
return ;
            }
            
int  port  =   80 ;
            
string  url  =  GetUrl(clientmessage, port);
            
#endregion
            
            
try
            {
                
#region  IP解析获取
                IPHostEntry IPHost
=  Dns.GetHostEntry(url);
                Write(
" -----------------------------请求开始--------------------------- " );
                Write(
" http:// "   +  IPHost.HostName);
                
string [] aliases  =  IPHost.Aliases;
                IPAddress[] address 
=  IPHost.AddressList; // 解析出要访问的服务器地址
                Write( " IP地址: "   +  address[ 0 ]);
                
#endregion
               

                
#region  创建中转Socket及建立连接
                IPEndPoint ipEndpoint 
=   new  IPEndPoint(address[ 0 ], port);
                Socket IPsocket 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                
// 创建连接Web服务器端的Socket对象
                IPsocket.Connect(ipEndpoint);
                
// Socket连Web接服务器
                 if  (IPsocket.Connected)
                {
                    Write(
" Socket 正确连接! " );
                }
                
#endregion
                
#region  发送中转请求
                IPsocket.Send(read, 
0 );
                Write(
" 发送字节: "   +  read.Length);
                
#endregion
                
#region  接收中转请求数据
                
int  length  =   0 , count  =   0 ;
                
do
                {
                    length 
=  IPsocket.Receive(recvBytes, count, IPsocket.Available,  0 );
                    count 
=  count  +  length;
                    Write(
" 正在接收数据... "   +  length);
                    System.Threading.Thread.Sleep(
100 ); // 关键点,请求太快数据接收不全
                }
                
while  (IPsocket.Available  >   0 );
                
#endregion
                
#region  关闭中转请求Socket
                IPsocket.Shutdown(SocketShutdown.Both);
                IPsocket.Close();
                
#endregion

                
#region  将中转请求收到的数据发回客户端
                clientSocket.Send(recvBytes, 
0 , count,  0 );
                Write(
" 正在返回数据... "   +  count);
                
#endregion
                
#region  结束请求,关闭客户端Socket
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
                recvBytes 
=   null ;
                Write(
" 完成,已关闭连接... " );
                Write(
" -----------------------------请求结束--------------------------- " );
                
#endregion
            }
            
catch  (Exception err)
            {
                System.Console.WriteLine(err.Message 
+  err.Source);
            }

        }
        
// 从请求头里解析出url和端口号
         private   string  GetUrl( string  clientmessage,  int  port)
        {
            
int  index1  =  clientmessage.IndexOf( '   ' );
            
int  index2  =  clientmessage.IndexOf( '   ' , index1  +   1 );
            
if  ((index1  ==   - 1 ||  (index2  ==   - 1 ))
            {
                
throw   new  IOException();
            }
            
string  part1  =  clientmessage.Substring(index1  +   1 , index2  -  index1).Trim();

            
string  url  =   string .Empty;
            
if  ( ! part1.Contains( " http:// " ))
            {
                part1 
=   " http:// "   +  part1;
            }
            Uri uri 
=   new  Uri(part1);
            url 
=  uri.Host;
            port 
=  uri.Port;
            
return  url;
        }
        
// 接收客户端的HTTP请求数据
         private   int  ReadMessage( byte [] readByte,  ref  Socket s,  ref   string  clientmessage)
        {
            
int  bytes  =  s.Receive(readByte, readByte.Length,  0 );
            clientmessage 
=  Encoding.ASCII.GetString(readByte);
            
return  bytes;
        }

        
private   void  Write( string  msg)
        {
            
//  return;
            System.Console.WriteLine(msg);
        }
    }
}

 

 

在控制台里调用:

 

代码
using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Diagnostics;
using  System.Net.Sockets;
using  System.Threading;
namespace  TCPProxy
{
    
class  Program
    {
        
static   void  Main( string [] args)
        {
                Listen(
8989 );
        }
        
static   void  Write( string  msg)
        {
            Console.WriteLine(msg);
        }

        
static   void  Listen( int  port)
        {
            Write(
" 准备监听端口: "   +  port);
            TcpListener tcplistener 
=   new  TcpListener(port);
            
try
            {
                tcplistener.Start();
            }
            
catch
            {
                Write(
" 该端口已被占用,请更换端口号!!! " );
                ReListen(tcplistener);
            }
            Write(
" 确认:y/n (yes or no): " );
            
string  isOK  =  Console.ReadLine();
            
if  (isOK  ==   " y " )
            {
                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();
                    System.Threading.Thread.Sleep(
10 );
                    
// 启动线程 
                }
            }
            
else
            {
                ReListen(tcplistener);
            }
        }
        
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);
            }
        }
    }
}

 

 

本人测试:

在打开IE-》工具->Internet选项->链接->局域网设置->代理连接-》输入IP和端口号

访问网站,查看控制台输出消息,页面访问正常,测试通过。

 

本来想测试下QQ代理,无奈本地已被封,服务器也没端口可用。有空回家再测了。

 

提供代码下载

 

你可能感兴趣的:(简单实现Http代理工具)