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

没想到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代理,无奈本地已被封,服务器也没端口可用。有空回家再测了。

 

提供代码下载

 

posted on 2010-06-03 10:53  路过秋天  阅读(4696)  评论(10编辑  收藏  举报
路过秋天