免费预览已结束,剩余13页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
目录一、绪论1二、需求分析2三、详细设计5四、软件测试9五、设计小结10参考文献11附录11一、绪论本次课设主要要做的是要理解winsock技术网络编程的技术,分析http代理应用程序设计原理,然后选择合适的开发环境用winsock技术来设计http代理的应用程序。首先先简单的介绍几个相关名词的基本概念:1.WinsockWindows下网络编程的规范Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口,现已成为Windows网络编程的事实上的标准。Windows Sockets规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。此外,在一个特定版本Windows的基础上,Windows Sockets也定义了一个二进制接口(ABI),以此来保证应用Windows Sockets API的应用程序能够在任何网络软件供应商的符合Windows Sockets协议的实现上工作。因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。2.http代理www对于每一个上网的人都再熟悉不过了,www连接请求就是采用的http协议,所以我们在浏览网页,下载数据(也可采用ftp协议)是就是用http代理。它通常绑定在代理服务器的80、3128、8080等端口上。3.http协议HTTP协议即超文本传输协议,是Internet上进行信息传输时使用最为广泛的一种非常简单的通信协议。部分局域网对协议进行了限制,只允许用户通过HTTP协议访问外部网站。4.http代理服务器代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站。在一般情况下,我们使用网络浏览器直接去连接其他Internet站点取得网络信息时,须送出Request信号来得到回答,然后对方再把信息以bit方式传送回来。代理服务器是介于浏览器和Web服务器之间的一台服务器,有了它之后,浏览器不是直接到Web服务器去取回网页而是向代理服务器发出请求,Request信号会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。而且,大部分代理服务器都具有缓冲的功能,就好象一个大的Cache,它有很大的存储空间,它不断将新取得数据储存到它本机的存储器上,如果浏览器所请求的数据在它本机的存储器上已经存在而且是最新的,那么它就不重新从Web服务器取数据,而直接将存储器上的数据传送给用户的浏览器,这样就能显著提高浏览速度和效率。更重要的是:Proxy Server(代理服务器)是Internet链路级网关所提供的一种重要的安全功能,它的工作主要在开放系统互联(OSI)模型的对话层。二、需求分析理解winsock技术网络编程技术,分析HTTP代理应用程序设计原理和程序流程,选择合适的开发环境,参考已有的HTTP程序功能,设计实现HTTP代理功能的应用程序。1. winsock的理解与分析这次课设要使用网络编程技术,这就要求掌握winsock的相关知识,因为winsock是Windows下网络编程的规范 ,是被广泛应用的、开放的、支持多种协议的网络编程接口,要使用winsock编程技术应该了解一些TCP/IP的基础知识,因为WinSock其实就是TCP/IP协议的一种封装,我们可以通过调用WinSock的接口函数来调用TCP/IP的各种功能,例如如果想用TCP/IP协议来发送数据,你就可以使用WinSock的接口函数Send()来调用TCP/IP的发送数据功能,至于具体怎么发送数据,WinSock已经帮你封装好了这种功能,当然这里的TCP/IP协议准确的说来应该是TCP/UDP/IP协议。Winsocket函数:Windows的Socket函数有许多,我没有做详细介绍,这里的函数都是简要说明其用途,这里的主要目的是为了后面的三个应用服务。函数说明: WSAStartup函数 初始化Winsock 声明 intWSAStarup(WORDwVersionRequested,LPWSADATAlpWSAData); 参数 wVersionRequested-要求使用Winsock的最低版本号 lpWSAData-Winsock的详细资料 返回值 当函数成功调用时返回0失败时返回非0的值 socket函数 用于生成socket(soketDescriptor) 声明 SOCKETsocket(intaf,inttype,intprotocol); 参数 af-地址家族(通常使用:AF_INET) type-socket的种类 SOCK_STREAM:用于TCP协议 SOCK_DGRAM:用于UDP协议 protocol-所使用的协议 返回值 当函数成功调用时返回一个新的SOCKET(SocketDescriptor)失败时返回INVALID_SOCKET. inet_addr函数 地址转换,把A.B.C.D的IP地址转换为32位长整数 声明 unsignedlonginet_addr(constcharFAR*cp); 参数 cp-指向IP地址字符串的指针 返回值 当函数成功调用时返回用32位整数表示的IP地址 失败时返回INADDR_NONE.gethostbyname函数 从主机名获取主机信息.声明 structhostentFAR*gethostbyname(constcharFAR*name);参数name-指向主机名字符串的指针 返回值 当函数成功调用时返回主机信息 失败时返回NULL(空值) recv函数 利用Socket进行接受数据. 声明intrecv(SOCKETs,charFAR*buf,intlen,intflags);参数 s-指向用Socket函数生成的SocketDescriptorbuf-接受数据的缓冲区(数组)的指针 len-缓冲区的大小 flag-调用方式(MSG_PEEK或MSG_OOB) 返回值 成功时返回收到的字节数. 如果连接被中断则返回0 失败时返回SOCKET_ERROR sendto函数 发送数据.声明 intsendto(SOCKETs,constcharFAR*buf,intlen,intflags,conststructsockaddrFAR*to,inttoken);参数 s-指向用Socket函数生成的SocketDescriptor buf-接受数据的缓冲区(数组)的指针 len-缓冲区的大小 flag-调用方式(MSG_DONTROUTE,MSG_OOB) to-指向发送方SOCKET地址的指针 token-发送方SOCKET地址的大小 返回值 成功时返回已经发送的字节数.失败时返回SOCKET_ERROR2有关http代理协议的体系结构本课设所做的是代理是一种应用层上面的代理,所代理的协议是HTTP,也就是经常见到的Web代理,网络代理就是一个连接客户端(设定需要代理的计算机)和服务器端(需要访问资源的服务器)的桥,以下是网络代理服务的一个典型模型图:代理服务的运行的流程:(1). 能够接收并解析客户端的请求。(2). 创建到服务器的新连接,并根据转发客户端的请求信息。(3). 接收服务器反馈的信息。(4). 能够发出或解释服务器的响应并将该响应传回给客户端。三、详细设计1.程序流程图和设计方案程序的流程图如下:实例连接web服务器上侦听端口,接收客户端浏览器发送来的Web请求信息解析出Web服务器的地址,创建socket实例通过创建的Socket传送客户端的Web请求数据包到Web服务器的80端口接收Web服务器返回页面数据把接收来的数据传送到客户端完成,实现了web代理设计方案:主要包括三个部分内容:1).创建一个Web代理类。2).Web代理服务的类的实例化。3). 通过这个Web代理类的实例实现Web代理服务。具体方案可以参见下文。2.选择开发环境,编译源程序选择visual studio .net 2003开发环境源程序编译及步骤:1).创建一个web代理类,命名WebProxy,编辑Proxy.cs文件:using System ;using System.Net ;using System.Net.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 ) ;tryIPHostEntry IPHost = Dns.Resolve ( URL ) ;Console.WriteLine ( 远程主机名: + IPHost.HostName ) ;string aliases = IPHost.Aliases ;IPAddress address = IPHost.AddressList ;Console.WriteLine ( Web服务器IP地址: + address0 ) ;/解析出要访问的服务器地址IPEndPoint ipEndpoint = new IPEndPoint ( address0 , 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 byte1024 ;/定义一个空间,存储来自客户端请求数据包Byte Buffer = null ;Encoding ASCII = Encoding.ASCII ;/设定编码Byte RecvBytes = new Byte4096 ;/定义一个空间,存储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 System.Net ;using System.Net.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地址为02,所有也输入此IP地址,在【端口】文本框中输入8000。客户端的设置完成之后,在确定IP地址为02的这台计算机已经运行代理程序后。打开客户端的IE浏览器,并输入要浏览的网址,就可以通过Web代理服务器来浏览网页了,运行结果如下图所示:五、设计小结虽然代理服务的实现原理相对简单,但具体实现其实还是很繁琐的。网络代理是一个内容丰富,实现复杂的论题,本课设所做的代理服务软件,无论在实现的协议种类,还是实现的功能,都只能算很小的一部分。这次课程设计使我感到收获不小,使我对http协议有了更深的了解,促进了对理论知识的消化与吸收,也巩固和完善了本门课程的知识体系结构。除此之外,对winsock语言的语法结构也有了一定的了解。通过这次课程设计,使自己在计算机网络方面的知识增加了很多,自己的编程能力也得到了很大的提高,尤其是对网络编程有了一定的了解,能够编写一些简单的网络程序了。在一周的课设时间里,自己常常跑到图书馆去翻阅各种有关的资料,不断的学习有关方面的知识,在编写源程序代码时又经常上网查阅各种知识,这样自己的知识不断的丰富,自己的编程水平也得到了很大的提高,通过网上一些人的介绍,自己的编程经验也丰富了许多。参考文献1 (美)罗/舒赫|译者:李春洪/李文中/叶保留,计算机网络,清华大学出版社2 邓亚平,计算机网络,电子工业出版社3 徐武/王贵柱/孔云龙 ,计算机网络工程与实训教程,电子工业出版社4 (美)克莱姆|译者:詹文军/杜晓峰/刘玉鹏,网络管理技术构架,人民邮电出版社5 /msdn/338/2315838_2.shtml附录WINDOWS环境下SOCKET基本函数:(1)WSAStartup函数int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。 例:假如一个程序要使用2.1版本的Socket,那么程序代码如下wVersionRequested = MAKEWORD( 2, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); (2)WSACleanup函数 int WSACleanup (void); 应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。 (3)socket函数SOCKET socket( int af, int type, int protocol ); 应用程序调用socket函数来创建一个能够进行网络通信的套接字。第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置PF_INET;第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;第三个参数指定应用程序所使用的通信协议。该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。下面是一个创建流套接字的例子: struct protoent *ppe; ppe=getprotobyname(tcp); SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe-p_proto); (4)closesocket函数 int closesocket( SOCKET s ); closesocket函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构,因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描述符表中的对应表项,并且把s对应的套接字数据结构的引用次数减1。 closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。 (5)send函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。该函数的第一个参数指定发送端套接字描述符;第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲区的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR) 注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。 (6)recv函数 int recv( SOCKET s, char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;第三个参数指明buf的长度;第四个参数一般置0。这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,只到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。 注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。 (7)bind函数 int bind( SOCKET s, const struct sockaddr FAR *name, int namelen ); 当创建了一个Socket以后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。客户程序一般不必调用bind函数来为其Socket绑定IP地址和断口号。该函数的第一个参数指定待绑定的Socket描述符;第二个参数指定一个sockaddr结构,该结构是这样定义的: struct sockaddr u_short sa_family; char sa_data14; ; sa_family指定地址族,对于TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字进行绑定时,我们通常使用另一个地址结构:struct sockaddr_in short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero8; ; 其中sin_family置AF_INET;sin_port指明端口号;sin_addr结构体中只有一个唯一的字段s_addr,表示IP地址,该字段是一个整数,一般用函数inet_addr()把字符串形式的IP地址转换成unsigned long型的整数值后再置给s_addr。有的服务器是多宿主机,至少有两个网卡,那么运行在这样的服务器上的服务程序在为其Socket绑定IP地址时可以把htonl(INADDR_ANY)置给s_addr,这样做的好处是不论哪个网段上的客户程序都能与该服务程序通信;如果只给运行在多宿主机上的服务程序的Socket绑定一个固定的IP地址,那么就只有与该IP地址处于同一个网段上的客户程序才能与该服务程序通信。我们用0来填充sin_zero数组,目的是让sockaddr_in结构的大小与sockaddr结构的大小一致。下面是一个bind函数调用的例子: struct
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年新能源产业新能源技术前沿研究报告及未来发展趋势
- 2025年民宿投诉处理合同协议
- 2025年民宿短租管理合同协议
- 2025年洛阳市老城区保安员招聘考试题库附答案解析
- 2025年门禁系统技术支持补充合同协议
- 电工过级考试题库及答案
- 2025年城市空中交通解决方案可行性分析
- 安全生产管理人员理论考试笔试试题(100题)含答案
- 2025年量子计算技术保密合同
- 2025年旅游产业数字化升级项目可行性研究报告及总结分析
- 我的家乡邢台内丘县宣传介绍
- 智能制造工程生涯人物访谈
- 大学英语四级作文
- 交通管理扣留车辆拖移、保管项目 投标方案(技术标)
- 气相色谱-质谱联用法测定鱼腥草挥发油中4种成分的含量
- 国际贸易理论与实务(英文版)PPT完整全套教学课件
- 故意杀人上诉状范文两篇
- 小工具批量处理邻区脚本实用操作
- 三年级科学下册《谁在水中溶解得多》实验报告单
- 高中数学 数列 4.4数学归纳法第1课时
- GB/T 7735-2004钢管涡流探伤检验方法
评论
0/150
提交评论