7. 用下列构造函数替代默认的构造函数。下面的代码是在Proxy类中创建一个构造函数。 Proxy类只有一个构造函数,并且这个构造函数只有一个参数,这个参数是Socket对象,它主要用来和客户端进行数据交换,是一个客户Socket.。
public Proxy ( Socket socket )
{
//
// TODO: 在此处添加构造函数逻辑
//
this.clientSocket = socket ;
}
8. 创建Proxy类中的Run方法,Run方法是Proxy类中唯一的方法。其功能是从客户端接收HTTP请求,并传送到Web服务器,然后从Web服务器接收反馈来的数据,并传送到客户端。为了实现这二个不同方面的数据传送,Run方法中是通过二个Socket实例来实现的。在编写Run方法的时候,要注意下面几点:
(1). 由于HTTP是TCP/IP参考模型中的应用层协议,它建立于TCP协议之上,所以创建的Socket实例使用的协议类型应该为TCP协议。下面代码是创建可以传送HTTP请求命令到Web服务器和接收来自Web服务器反馈来信息的Socket实例:
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
(2). 另外一个Socket是在代理服务程序侦听端口号,接收挂起的连接请求时候得到的,以此Socket为参数,利用Proxy类中的构造函数,来创建一个Proxy实例的。此Socket实现从客户端接收HTTP请求信息,并传送数据到客户端。
Socket创建和使用是实现Web代理软件的关键,具体实现方法是在构造函数代码后面,输入下列代码,创建Proxy类的Run方法:
public void Run ( )
{
string clientmessage = " " ;
//存放来自客户端的HTTP请求字符串
string URL = " " ;
//存放解析出地址请求信息
int bytes = ReadMessage ( read , ref clientSocket , ref clientmessage ) ;
if ( bytes == 0 )
{
return ;
}
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 ) ;
int index3 = part1.IndexOf ( '/' , index1 + 8 ) ;
int index4 = part1.IndexOf ( ' ' , index1 + 8 ) ;
int index5 = index4 - index3 ;
URL = part1.Substring ( index1 + 4 , ( part1.Length - index5 ) - 8 ) ;
try
{
IPHostEntry IPHost = Dns.Resolve ( URL ) ;
Console.WriteLine ( "远程主机名: " + IPHost.HostName ) ;
string [] aliases = IPHost.Aliases ;
IPAddress[] address = IPHost.AddressList ;
Console.WriteLine ( "Web服务器IP地址:" + address[0] ) ;
//解析出要访问的服务器地址
IPEndPoint ipEndpoint = new IPEndPoint ( address[0] , 80 ) ;
Socket IPsocket = new Socket ( AddressFamily.InterNetwork , SocketType.Stream , ProtocolType.Tcp ) ;
//创建连接Web服务器端的Socket对象
IPsocket.Connect ( ipEndpoint ) ;
//Socket连Web接服务器
if ( IPsocket.Connected )
Console.WriteLine ( "Socket 正确连接!" ) ;
string GET = clientmessage ;
Byte[] ByteGet = ASCII.GetBytes ( GET ) ;
IPsocket.Send ( ByteGet , ByteGet.Length , 0 ) ;
//代理访问软件对服务器端传送HTTP请求命令
Int32 rBytes = IPsocket.Receive ( RecvBytes , RecvBytes.Length , 0 ) ;
//代理访问软件接收来自Web服务器端的反馈信息
Console.WriteLine ( "接收字节数:" + rBytes.ToString ( ) ) ;
String strRetPage = null ;
strRetPage = strRetPage + ASCII.GetString ( RecvBytes , 0 , rBytes ) ;
while ( rBytes > 0 )
{
rBytes = IPsocket.Receive ( RecvBytes , RecvBytes.Length , 0 ) ;
strRetPage = strRetPage + ASCII.GetString ( RecvBytes , 0 , rBytes ) ;
}
IPsocket.Shutdown ( SocketShutdown.Both ) ;
IPsocket.Close ( ) ;
SendMessage ( clientSocket , strRetPage ) ;
//代理服务软件往客户端传送接收到的信息
}
catch ( Exception exc2 )
{
Console.WriteLine ( exc2.ToString ( ) ) ;
}
}
//接收客户端的HTTP请求数据
private int ReadMessage ( byte [ ] ByteArray , ref Socket s , ref String clientmessage )
{
int bytes = s.Receive ( ByteArray , 1024 , 0 ) ;
string messagefromclient = Encoding.ASCII.GetString ( ByteArray ) ;
clientmessage = ( String )messagefromclient ;
return bytes ;
}
//传送从Web服务器反馈的数据到客户端
private void SendMessage ( Socket s , string message )
{
Buffer = new Byte[message.Length + 1] ;
int length = ASCII.GetBytes ( message , 0 , message.Length , Buffer , 0 ) ;
Console.WriteLine ( "传送字节数:" + length.ToString ( ) ) ;
s.Send ( Buffer , length , 0 ) ;
}
9. 在定义Proxy类代码区中加入下列代码,下列代码是定义Proxy类中的使用的一些变量,这些变量主要是在后面的定义Run方法中使用。
Socket clientSocket ;
Byte[] read = new byte[1024] ;
//定义一个空间,存储来自客户端请求数据包
Byte [] Buffer = null ;
Encoding ASCII = Encoding.ASCII ;
//设定编码
Byte[] RecvBytes = new Byte[4096] ;
//定义一个空间,存储Web服务器返回的数据
10. 至此,Proxy类的定义过程就完成了。把Proxy类实例化非常简单,和以前用的其他完全一样,具体语法如下:
public Proxy ( Socket socket );
参数:socket为一个Scoket实例
下面代码是创建一个Proxy实例:
Proxy proxy = new Proxy ( socket ) ;
