基于winsock技术编制HTTP代理服务器程序

基于winsock技术编制HTTP代理服务器程序

xxx

xxxxxxxxxxxxxxxx

摘要:HTTP协议即超文本传输协议,是Internet上进行信息传输时使用最为广泛的一种非常简单的通信协议。

部分局域网对协议进行了限制,只允许用户通过HTTP协议访问外部网站。此次编制利用winsock技术

网络编程的技术,分析http代理应用程序设计原理,然后选择合适的开发环境用winsock技术来设计

http代理的应用程序。

关键词:HTTP协议 winsock 信息传输

一.研究背景

Windows下网络编程的规范-Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口,现已成为Windows网络编程的事实上的标准。Windows Sockets规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。此外,在一个特定版本Windows的基础上,Windows Sockets也定义了一个二进制接口(ABI),以此来保证应用Windows Sockets API的应用程序能够在任何网络软件供应商的符合Windows Sockets协议的实现上工作。因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。

本次编制是基于winsock网络编程的技术,分析http代理应用程序设计原理,然后选择合适的开发环境用winsock技术来设计http代理的应用程序。

1.http代理

www对于每一个上网的人都再熟悉不过了,www连接请求就是采用的http协议,所以我们在浏览网页,下载数据(也可采用ftp协议)是就是用http代理。它通常绑定在代理服务器的80、3128、8080等端口上。

2.http协议

HTTP协议即超文本传输协议,是Internet上进行信息传输时使用最为广泛的一种非常简单的通信协议。部分局域网对协议进行了限制,只允许用户通过HTTP协议访问外部网站。

3.http代理服务器

代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站。在一般情况下,我们使用网络浏览器直接去连接其他Internet站点取得网络信息时,须送出Request信号来得到回答,然后对方再把信息以bit方式传送回来。

代理服务器是介于浏览器和Web服务器之间的一台服务器,有了它之后,浏览器不是直接到Web服务器去取回网页而是向代理服务器发出请求,Request信号会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。而且,大部分代理服务器都具有缓冲的功能,就好象一个大的Cache,它有很大的存储空间,它不断将新取得数据储存到它本机的存储器上,如果浏览器所请求的数据在它本机的存储器上已经存在而且是最新的,那么它就不重新从Web服务器取数据,而直接将存储器上的数据传送给用户的浏览器,这样就能显著提高浏览速度和效率。

更重要的是:Proxy Server(代理服务器)是Internet链路级网关所提供的一种重要

的安全功能,它的工作主要在开放系统互联(OSI)模型的对话层。

二.winsock

理解winsock网络编程技术,分析HTTP代理应用程序设计原理和程序流程,选择合适的开发环境,参考已有的HTTP程序功能,设计实现HTTP代理功能的应用程序。

使用网络编程技术,这就要求掌握Winsock的相关知识,因为WinSock其实就是TCP/IP协议的一种封装,我们可以通过调用WinSock的接口函数来调用TCP/IP的各种功能,例如如果想用TCP/IP协议来发送数据,你就可以使用WinSock的接口函数Send()来调用TCP/IP的发送数据功能,至于具体怎么发送数据,WinSock已经帮你封装好了这种功能,当然这里的TCP/IP协议准确的说来应该是TCP/UDP/IP协议。

Winsocket函数:

Windows的Socket函数有许多, 我没有做详细介绍,这里的函数都是简要说明其用途, 这里的主要目的是为了后面的三个应用服务。

函数说明:

1.WSAStartup函数:初始化Winsock

[声明] int WSAStarup(WORD wVersionRequested,LPWSADATA lpWSAData);

[参数] wVersionRequested - 要求使用Winsock的最低版本号

lpWSAData - Winsock的详细资料

[返回值] 当函数成功调用时返回0,失败时返回非0的值

2.socket函数用于生成socket(soket Descriptor)

[声明] SOCKET socket(int af,int type,int protocol);

[参数] af - 地址家族(通常使用:AF_INET)

type - socket的种类

SOCK_STREAM : 用于TCP协议

SOCK_DGRAM : 用于UDP协议

protocol - 所使用的协议

[返回值] 当函数成功调用时返回一个新的SOCKET(Socket Descriptor);失败时返回INVALID_SOCKET.

3.inet_addr函数:地址转换, 把"A.B.C.D"的IP地址转换为32位长整数

[声明] unsigned long inet_addr ( const char FAR *cp );

[参数] cp - 指向IP地址字符串的指针

[返回值] 当函数成功调用时返回用32位整数表示的IP地址;失败时返回INADDR_NONE.

4.gethostbyname函数:从主机名获取主机信息.

[声明] struct hostent FAR * gethostbyname (const char FAR *name); [参数] name - 指向主机名字符串的指针

[返回值] 当函数成功调用时返回主机信息;失败时返回NULL(空值).

5.recv函数:利用Socket进行接受数据.

[声明] int recv (SOCKET s ,char FAR *buf,int len,int flags );

[参数] s - 指向用Socket函数生成的Socket Descriptor

buf - 接受数据的缓冲区(数组)的指针

len - 缓冲区的大小

flag - 调用方式(MSG_PEEK 或MSG_OOB)

[返回值]成功时返回收到的字节数.如果连接被中断则返回0。失败时返回SOCKET_ERROR

6.sendto函数:发送数据.

[声明]

int sendto (SOCKET s,constchar FAR *buf ,int len,int flags,const s truct sockaddr FAR *to,int token);

[参数]

s - 指向用Socket函数生成的Socket Descriptor

buf - 接受数据的缓冲区(数组)的指针

len - 缓冲区的大小

flag - 调用方式(MSG_DONTROUTE , MSG_OOB)

to - 指向发送方SOCKET地址的指针

token - 发送方SOCKET地址的大小

[返回值] 成功时返回已经发送的字节数.失败时返回SOCKET_ERROR

二.有关http代理协议的体系结构

代理是一种应用层上面的代理,所代理的协议是HTTP,也就是经常见到的Web代理,网络代理就是一个连接客户端(设定需要代理的计算机)和服务器端(需要访问资源的服务器)的桥,以下是网络代理服务的一个典型模型图:

图3-1 本体学习周期

代理服务的运行的流程:

(1). 能够接收并解析客户端的请求。

(2). 创建到服务器的新连接,并根据转发客户端的请求信息。

(3). 接收服务器反馈的信息。

(4). 能够发出或解释服务器的响应并将该响应传回给客户端。

三.详细设计

1.设计方案:

主要包括三个部分内容:

1)创建一个Web代理类。

2)Web代理服务的类的实例化。

3)通过这个Web代理类的实例实现Web代理服务。

设计流程图如下:

侦听端口,接收客户端浏览器发送来的Web请求信息

解析出Web服务器的地址,创建socket实例

实例连接web服务器上

通过创建的Socket传送客户端的Web请求数据包

到Web服务器的80端口

接收Web服务器返回页面数据

把接收来的数据传送到客户端

完成,实现了web代理

2.选择开发环境,编译源程序

选择visual studio .net 2003开发环境,源程序编译及步骤:

1)创建一个web代理类,命名WebProxy,编辑Proxy.cs文件:

using System ;

using https://www.360docs.net/doc/8f725352.html, ;

using https://www.360docs.net/doc/8f725352.html,.Sockets ;

using System.Text ;

using System.IO ;//以上代码是导入Proxy.cs中要使用到的命名空间

2)用下列构造函数替代默认的构造函数。下面的代码是在Proxy类中创建一个构造函数。 Proxy类只有一个构造函数,并且这个构造函数只有一个参数,这个参数是Socket对象,它主要用来和客户端进行数据交换,是一个客户Socket。

public Proxy ( Socket socket )

{ this.clientSocket = socket ; }

3)创建Proxy类中的Run方法,Run方法是Proxy类中唯一的方法。其功能是从客户端接收HTTP请求,并传送到Web服务器,然后从Web服务器接收反馈来的数据,并传送到客户端。为了实现这二个不同方面的数据传送,Run方法中是通过二个Socket 实例来实现的。由于HTTP是TCP/IP参考模型中的应用层协议,它建立于TCP协议之上,所以创建的Socket实例使用的协议类型应该为TCP协议。下面代码是创建可以传送HTTP请求命令到Web服务器和接收来自Web服务器反馈来信息的Socket实例:

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

4)另外一个Socket是在代理服务程序侦听端口号,接收挂起的连接请求时候得到的,以此Socket为参数,利用Proxy类中的构造函数,来创建一个Proxy实例的。此

Socket实现从客户端接收HTTP请求信息,并传送数据到客户端。

创建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接服务器

5)在定义Proxy类代码区中加入下列代码:

Socket clientSocket ;

Byte[] read = new byte[1024] ;

//定义一个空间,存储来自客户端请求数据包

Byte [] Buffer = null ;

Encoding ASCII = Encoding.ASCII ;

//设定编码

Byte[] RecvBytes = new Byte[4096] ;

//定义一个空间,存储Web服务器返回的数据

6) 把Proxy类实例化具体语法如下:

public Proxy ( Socket socket );

参数:socket为一个Scoket实例

Proxy proxy = new Proxy ( socket ) ;//创建一个Proxy实例:

7). 利用Proxy类,实现Web代理:

利用上面创建的Proxy类,实现Web代理程序的具体实现步骤,Proxy类被定义在命名空间WebProxy中。

在Class1.cs源文件的开头导入下列命名空间:

using System ;

using https://www.360docs.net/doc/8f725352.html, ;

using https://www.360docs.net/doc/8f725352.html,.Sockets ;

using System.Text ;

using System.IO ;

using System.Threading ;

using WebProxy ; //其中命名空间WebProxy是Proxy类所处的位置,具体可以参阅Proxy.cs源文件中命名空间的定义。

8).在Main函数中添加下列代码,下列代码是利用Proxy类,来实现Web代理程序。

const int port = 8000 ; //定义端口号

TcpListener tcplistener = new TcpListener ( port ) ;

Console.WriteLine ( "侦听端口号: " + port.ToString ( ) ) ;

tcplistener.Start ( ) ;//侦听端口号

while ( true )

{

Socket socket = tcplistener.AcceptSocket ( ) ;

//并获取传送和接收数据的Scoket实例

Proxy proxy = new Proxy ( socket ) ;//Proxy类实例化

Thread thread = new Thread ( new ThreadStart ( proxy.Run ) ) ;

//创建线程

thread.Start ( ) ;//启动线程 }

至此简单Web代理程序就算是完成了。

软件测试

此代理程序侦听的是8000端口号。

代理程序要通过二台计算机才能够实现。其中的一台计算机运行Web代理程序,充当Web代理服务器。另外一台计算机充当客户机,通过Web代理服务器来浏览网页。在确定Web代理软件运行后,对客户机进行必要的设置:通过设置IE浏览器的Internet选项设置代理服务器相关的信息,在其中的地址文本框中输入代理服务器的IP地址,由于测试的代理服务器的IP地址为"122.93.54.202",所有也输入此IP地址,在端口文本框中输入"8000"。

客户端的设置完成之后,在确定IP地址为"122.93.54.202"的这台计算机已经运行代理程序后。打开客户端的IE浏览器,并输入要浏览的网址,就可以通过Web代理服务器来浏览网页了,运行结果如下图所示:

六.总结及未来研究方向

虽然代理服务的实现原理相对简单,但具体实现其实还是很繁琐的。网络代理是一个内容丰富,实现复杂的论题,本课设所做的代理服务软件,无论在实现的协议种类,还是实现的功能,都只能算很小的一部分。

这次课程设计使我感到收获不小,使我对http协议有了更深的了解,促进了对理论知识的消化与吸收,也巩固和完善了本门课程的知识体系结构。除此之外,对winsock语言的语法结构也有了一定的了解。

通过这次课程设计,使自己在计算机网络方面的知识增加了很多,自己的编程能力也得到了很大的提高,尤其是对网络编程有了一定的了解,能够编写一些简单的网络程序了。在一周的课设时间里,自己常常跑到图书馆去翻阅各种有关的资料,不断的学习有关方面的知识,在编写源程序代码时又经常上网查阅各种知识,这样自己的知识不断的丰富,自己的编程水平也得到了很大的提高,通过网上一些人的介绍,自己的编程经验也丰富了许多。

参考文献

[1](美)罗//舒赫|译者:李春洪//李文中//叶保留,《计算机网络》,清华大学出版社

[2] 邓亚平,《计算机网络》,电子工业出版社

[3] 徐武//王贵柱//孔云龙,《计算机网络工程与实训教程》,电子工业出版社

[4] 谈子敬,施伯乐.DTD的规范化.计算机研究与发展,2004,41(4):594~601

[5](美)克莱姆|译者:詹文军//杜晓峰//刘玉鹏,《网络管理技术构架》,人民邮电出版社

[6]https://www.360docs.net/doc/8f725352.html,/msdn/338/2315838_2.shtml

[7] 朱福喜,尹为民,余振坤 . Java 语言与面向对象程序设计 .武汉大学出版社,2002.

[8]RFC2616. Hypertext Transfer Protocol -- HTTP/1.1. NetworkWorking Group.1999.

相关文档
最新文档