using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
using System.Collections;
namespace HttpProxy
{
public class HttpProxy
{
int ProxyPort;
/// <summary>
/// 代理服务器入口类构造函数
/// </summary>
/// <param name="Port">Http Proxy监听的端口</param>
public HttpProxy( int Port)
{
ProxyPort = Port;
}
/// <summary>
/// 启动Http代理服务器
/// </summary>
public void Start( )
{
TcpListener tcplistener = null;
try
{
// 开始监听端口
tcplistener = new TcpListener(Dns.GetHostAddresses(Dns.GetHostName())[0], ProxyPort);
tcplistener.Start();
Console.WriteLine("侦听端口号: " + ProxyPort.ToString());
}
catch (Exception e)
{
Console.WriteLine("启动代理服务器失败: " + e.Message);
}
while (true)
{
try
{
// 接受客户端连接
Socket socket = tcplistener.AcceptSocket();
HttpSession Session = new HttpSession(socket);
// 启动新线程,处理连接
Thread thread = new Thread(new ThreadStart(Session.Start));
thread.Start();
}
catch( Exception e )
{
Console.WriteLine("接受客户端连接异常: " + e.Message );
}
}
}
}
public class HttpSession
{
// 客户端socket
Socket ClientSocket;
// 设定编码
Encoding ASCII = Encoding.ASCII;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="socket">客户端socket</param>
public HttpSession(Socket socket)
{
this.ClientSocket = socket;
}
public void Start()
{
// 客户端缓冲区,读取客户端命令
Byte[] ReadBuff = new byte[1024 * 10];
try
{
int Length = ClientSocket.Receive(ReadBuff);
// 没有读到数据
if (0 == Length)
{
Console.WriteLine("从客户端读取命令错误");
ClientSocket.Shutdown(SocketShutdown.Both);
ClientSocket.Close();
return;
}
}
// 读取出现异常
catch (Exception e)
{
Console.WriteLine("读取客户端异常: " + e.Message);
}
// 来自客户端的HTTP请求字符串
string ClientMsg = ASCII.GetString(ReadBuff);
// 根据rnrn截取请求行
string Line = ClientMsg.Substring(0, ClientMsg.IndexOf("rn"));
string[] CmdArray = Line.Split(' ');
// GET http://www.test.com:80/index.php HTTP/1
// CONNECT www.test.com:443 HTTP/1
string Cmd = CmdArray[0];
string RawUrl = CmdArray[1];
Console.WriteLine("原始请求: ", Line);
// CONNECT请求
if (Cmd == "CONNECT")
{
DoConnect(RawUrl);
}
// GET,POST和其他
else
{
DoOther(RawUrl, ClientMsg);
}
}
/// <summary>
/// 处理CONNECT命令,此处作用是支持QQ,MSN,以及多级代理串联等
/// </summary>
/// <param name="RawUrl"></param>
private void DoConnect( string RawUrl )
{
string[] Args = RawUrl.Split( ':' );
string Host = Args[0];
int Port = int.Parse(Args[1]);
Socket ServerSocket = null;
try
{
IPAddress[] IpList = Dns.GetHostEntry(Host).AddressList;
Console.WriteLine("尝试连接:", IpList[0], Port);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServerSocket.Connect(IpList[0], Port);
}
catch (Exception e)
{
Console.WriteLine("连接真实服务器异常: " + e.Message);
}
// 连接真实服务器成功
if (ServerSocket.Connected)
{
ClientSocket.Send( ASCII.GetBytes("HTTP/0 200 Connection establishedrnrn") );
}
else
{
ClientSocket.Shutdown(SocketShutdown.Both);
ClientSocket.Close();
}
// 开始转发数据
ForwardTcpData(ClientSocket, ServerSocket);
}
/// <summary>
/// 处理GET,POST等命令。使用了POLL,在代理服务器中强制去掉了Keep-Alive能力
/// </summary>
/// <param name="RawUrl"></param>
/// <param name="ClientMsg"></param>
public void DoOther(string RawUrl, string ClientMsg)
{
RawUrl = RawUrl.Substring(0 + "http://".Length);
int Port;
string Host;
string Url;
// 下面是分割处理请求,此处应该用正则匹配,不过我不擅长,因此手动切割,—_—!
int index1 = RawUrl.IndexOf(':');
// 没有端口
if (index1 == -1)
{
Port = 80;
int index2 = RawUrl.IndexOf('/');
// 没有目录
if (index2 == -1)
{
Host = RawUrl;
Url = "/";
}
else
{
Host = RawUrl.Substring(0, index2);
Url = RawUrl.Substring(index2);
}
}
else
{
int index2 = RawUrl.IndexOf('/');
// 没有目录
if (index2 == -1)
{
Host = RawUrl.Substring(0, index1);
Port = IntParse(RawUrl.Substring(index1 + 1));
Url = "/";
}
else
{
// /出现在:之前,则说明:后面的不是端口
if (index2 < index1)
{
Host = RawUrl.Substring(0, index2);
Port = 80;
}
else
{
Host = RawUrl.Substring(0, index1);
Port = IntParse(RawUrl.Substring(index1 + 1, index2 - index1 - 1));
}
Url = RawUrl.Substring(index2);
}
}
Console.WriteLine("Host is:, Port is:, Url is:", Host, Port, Url);
IPAddress[] address = null;
try
{
IPHostEntry IPHost = Dns.GetHostEntry(Host);
address = IPHost.AddressList;
Console.WriteLine("Web服务器IP地址: " + address[0]);
}
catch( Exception e )
{
Console.WriteLine( "解析服务器地址异常: " + e.Message );
}
Socket IPsocket = null;
try
{
// 连接到真实WEB服务器
1 2 下一页