粗糙的C#版HTTP代理.docx

上传人:b****5 文档编号:8009136 上传时间:2023-01-27 格式:DOCX 页数:22 大小:20.04KB
下载 相关 举报
粗糙的C#版HTTP代理.docx_第1页
第1页 / 共22页
粗糙的C#版HTTP代理.docx_第2页
第2页 / 共22页
粗糙的C#版HTTP代理.docx_第3页
第3页 / 共22页
粗糙的C#版HTTP代理.docx_第4页
第4页 / 共22页
粗糙的C#版HTTP代理.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

粗糙的C#版HTTP代理.docx

《粗糙的C#版HTTP代理.docx》由会员分享,可在线阅读,更多相关《粗糙的C#版HTTP代理.docx(22页珍藏版)》请在冰豆网上搜索。

粗糙的C#版HTTP代理.docx

粗糙的C#版HTTP代理

粗糙的C#版HTTP代理

2008-8-50:

38:

21

粗糙的C#版HTTP代理

说说这段代码的问题吧。

首先是字符串切割的问题,要将客户端提交过来的GET,POST等原始请求切割,分离出主机名,端口,URL等数据。

这里用正则匹配是最好的,遗憾的是我不擅长此道,所以使用了手动切割的办法,很笨重繁琐,但是毕竟它工作得很好。

第二个问题是Keep-Alive的问题,这里我没有处理好。

最开始我在httpproxy里面修改客户端请求,强行将keep-alive修改为close,但是发现在某些站点的时候会出错。

于是使用了类似select的方法读取数据,直到超时关闭两端的连接。

我猜测,这里如果解析content-length会更好,但是略微繁琐了点,还是等我仔细阅读下RFC再看怎么修改吧。

第三个是CONNECT方法的问题,这个到很简单,转发数据就行了,因此是这个代码中写得最好的一部分,用来登陆QQ还是不错的。

说实话,我不喜欢HTTP这种太宽松的协议,感觉灵活得让我难以把握。

直接看代码吧,我加了很多debug信息,真的要用就去掉好了。

调用这个类很简单,看main函数的实现就好了。

为了方便贴代码,我写的时候就把三个类写到一个文件里面去了。

顺便要说的是,虽然有类,但是没有任何面向对象的东西——这也再次证明,其实我算不上一个程序员,最多是个代码爱好者。

usingSystem;

usingSystem.Net;

usingSystem.Net.Sockets;

usingSystem.Text;

usingSystem.IO;

usingSystem.Threading;

usingSystem.Collections;

namespaceHttpProxy

{

publicclassHttpProxy

{

intProxyPort;

///

///代理服务器入口类构造函数

///

///HttpProxy监听的端口

publicHttpProxy(intPort)

{

ProxyPort=Port;

}

///

///启动Http代理服务器

///

publicvoidStart()

{

TcpListenertcplistener=null;

try

{

//开始监听端口

tcplistener=newTcpListener(Dns.GetHostAddresses(Dns.GetHostName())[0],ProxyPort);

tcplistener.Start();

Console.WriteLine("侦听端口号:

"+ProxyPort.ToString());

}

catch(Exceptione)

{

Console.WriteLine("启动代理服务器失败:

"+e.Message);

}

while(true)

{

try

{

//接受客户端连接

Socketsocket=tcplistener.AcceptSocket();

HttpSessionSession=newHttpSession(socket);

//启动新线程,处理连接

Threadthread=newThread(newThreadStart(Session.Start));

thread.Start();

}

catch(Exceptione)

{

Console.WriteLine("接受客户端连接异常:

"+e.Message);

}

}

}

}

publicclassHttpSession

{

//客户端socket

SocketClientSocket;

//设定编码

EncodingASCII=Encoding.ASCII;

///

///构造函数

///

///客户端socket

publicHttpSession(Socketsocket)

{

this.ClientSocket=socket;

}

publicvoidStart()

{

//客户端缓冲区,读取客户端命令

Byte[]ReadBuff=newbyte[1024*10];

try

{

intLength=ClientSocket.Receive(ReadBuff);

//没有读到数据

if(0==Length)

{

Console.WriteLine("从客户端读取命令错误");

ClientSocket.Shutdown(SocketShutdown.Both);

ClientSocket.Close();

return;

}

}

//读取出现异常

catch(Exceptione)

{

Console.WriteLine("读取客户端异常:

"+e.Message);

}

//来自客户端的HTTP请求字符串

stringClientMsg=ASCII.GetString(ReadBuff);

//根据rnrn截取请求行

stringLine=ClientMsg.Substring(0,ClientMsg.IndexOf("rn"));

string[]CmdArray=Line.Split('');

//GET

:

80/index.phpHTTP/1

//CONNECT:

443HTTP/1

stringCmd=CmdArray[0];

stringRawUrl=CmdArray[1];

Console.WriteLine("原始请求:

",Line);

//CONNECT请求

if(Cmd=="CONNECT")

{

DoConnect(RawUrl);

}

//GET,POST和其他

else

{

DoOther(RawUrl,ClientMsg);

}

}

///

///处理CONNECT命令,此处作用是支持QQ,MSN,以及多级代理串联等

///

///

privatevoidDoConnect(stringRawUrl)

{

string[]Args=RawUrl.Split(':

');

stringHost=Args[0];

intPort=int.Parse(Args[1]);

SocketServerSocket=null;

try

{

IPAddress[]IpList=Dns.GetHostEntry(Host).AddressList;

Console.WriteLine("尝试连接:

",IpList[0],Port);

ServerSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

ServerSocket.Connect(IpList[0],Port);

}

catch(Exceptione)

{

Console.WriteLine("连接真实服务器异常:

"+e.Message);

}

//连接真实服务器成功

if(ServerSocket.Connected)

{

ClientSocket.Send(ASCII.GetBytes("HTTP/0200Connectionestablishedrnrn"));

}

else

{

ClientSocket.Shutdown(SocketShutdown.Both);

ClientSocket.Close();

}

//开始转发数据

ForwardTcpData(ClientSocket,ServerSocket);

}

///

///处理GET,POST等命令。

使用了POLL,在代理服务器中强制去掉了Keep-Alive能力

///

///

///

publicvoidDoOther(stringRawUrl,stringClientMsg)

{

RawUrl=RawUrl.Substring(0+"http:

//".Length);

intPort;

stringHost;

stringUrl;

//下面是分割处理请求,此处应该用正则匹配,不过我不擅长,因此手动切割,—_—!

intindex1=RawUrl.IndexOf(':

');

//没有端口

if(index1==-1)

{

Port=80;

intindex2=RawUrl.IndexOf('/');

//没有目录

if(index2==-1)

{

Host=RawUrl;

Url="/";

}

else

{

Host=RawUrl.Substring(0,index2);

Url=RawUrl.Substring(index2);

}

}

else

{

intindex2=RawUrl.IndexOf('/');

//没有目录

if(index2==-1)

{

Host=RawUrl.Substring(0,index1);

Port=IntParse(RawUrl.Substring(index1+1));

Url="/";

}

else

{

///出现在:

之前,则说明:

后面的不是端口

if(index2

{

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("Hostis:

Portis:

Urlis:

",Host,Port,Url);

IPAddress[]address=null;

try

{

IPHostEntryIPHost=Dns.GetHostEntry(Host);

address=IPHost.AddressList;

Console.WriteLine("Web服务器IP地址:

"+address[0]);

}

catch(Exceptione)

{

Console.WriteLine("解析服务器地址异常:

"+e.Message);

}

SocketIPsocket=null;

try

{

//连接到真实WEB服务器

IPEndPointipEndpoint=newIPEndPoint(address[0],Port);

IPsocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

IPsocket.Connect(ipEndpoint);

//对WEB服务器端传送HTTP请求命令,将原始HTTP请求中HTTPPROXY部分包装去掉

stringReqData=ClientMsg;

//改写头中的URL,

ReqData=ReqData.Replace("http:

//"+RawUrl,Url);

//按照rn切分HTTP头

string[]ReqArray=ReqData.Split(newstring[1]{"rn"},StringSplitOptions.None);

ReqData="";

//改写Keep-Alive等字段

for(intindex=0;index

{

/*

if(ReqArray[index].StartsWith("Accept-Encoding:

"))

{

ReqArray[index]="Accept-Encoding:

deflate";

}

*/

if(ReqArray[index].StartsWith("Proxy-Connection:

"))

{

ReqArray[index]=ReqArray[index].Replace("Proxy-Connection:

","Connection:

");

//ReqArray[index]="Connection:

close";

}

/*

elseif(ReqArray[index].StartsWith("Keep-Alive:

"))

{

ReqArray[index]="";

}

*/

//修改后的字段组合成请求

if(ReqArray[index]!

="")

{

ReqData=ReqData+ReqArray[index]+"rn";

}

}

ReqData=ReqData.Trim();

byte[]SendBuff=ASCII.GetBytes(ReqData);

IPsocket.Send(SendBuff);

}

catch(Exceptione)

{

Console.WriteLine("发送请求到服务器异常:

"+e.Message);

}

//使用Poll来判断完成,某些站点会出问题

while(true)

{

Byte[]RecvBuff=newbyte[1024*20];

try

{

if(!

IPsocket.Poll(15*1000*1000,SelectMode.SelectRead))

{

Console.WriteLine("HTTP超时,关闭连接");

break;

}

}

catch(Exceptione)

{

Console.WriteLine("Poll:

"+e.Message);

break;

}

intLength=0;

try

{

Length=IPsocket.Receive(RecvBuff);

if(0==Length)

{

Console.WriteLine("服务端关闭");

break;

}

Console.WriteLine("从服务端收到字节",Length);

}

catch(Exceptione)

{

Console.WriteLine("Recv:

"+e.Message);

break;

}

try

{

Length=ClientSocket.Send(RecvBuff,Length,0);

Console.WriteLine("发送字节到客户端",Length);

}

catch(Exceptione)

{

Console.WriteLine("Send:

"+e.Message);

}

}

/*

//根据接收字节数来判断完成,某些站点会出问题

try

{

while(true)

{

Byte[]RecvBuff=newbyte[1024*10];

intLength=IPsocket.Receive(RecvBuff);

if(Length<=0)

{

Console.WriteLine("从服务端接收数据完成");

break;

}

Console.WriteLine("从服务端收到字节",Length);

Length=ClientSocket.Send(RecvBuff,Length,0);

Console.WriteLine("发送字节到客户端",Length);

}

}

catch(Exceptione)

{

Console.WriteLine(e.Message);

}

*/

try

{

ClientSocket.Shutdown(SocketShutdown.Both);

ClientSocket.Close();

IPsocket.Shutdown(SocketShutdown.Both);

IPsocket.Close();

}

catch(Exceptione)

{

//Console.WriteLine(e.Message);

}

}

///

///在客户端和服务器之间中转数据

///

///客户端socket

///服务端socket

privatevoidForwardTcpData(Socketclient,Socketserver)

{

ArrayListReadList=newArrayList

(2);

while(true)

{

ReadList.Clear();

ReadList.Add(client);

ReadList.Add(server);

try

{

Socket.Select(ReadList,null,null,1*1000*1000);

}

catch(SocketExceptione)

{

Console.WriteLine("Selecterror:

"+e.Message);

break;

}

//超时

if(ReadList.Count==0)

{

//Console.WriteLine("Timeout");

continue;

}

//客户端可读

if(ReadList.Contains(client))

{

byte[]Recv=newbyte[1024*10];

intLength=0;

try

{

Length=client.Receive(Recv,Recv.Length,0);

if(Length==0)

{

Console.WriteLine("Clientisdisconnect.");

break;

}

Console.WriteLine("Recvbytesfromclient",Length);

}

catch(Exceptione)

{

Console.WriteLine("Readfromclienterror:

"+e.Message);

break;

}

try

{

Length=server.Send(Recv,Length,0);

Console.WriteLine("Writebytestoser

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1