金湘虹 倪卫东(无锡职业技术学院江苏・无锡214121)
摘要
以Jigsaw为例,详细描述了HttpProxy的运行机制和实现方法,其中包括Jigsaw配置成Proxy服务器、网络资源的封装、Http通讯协议的实现、Socket及SeverSocket的运用以及线程机制的管理与实现。
关键词ProxyHttp协议 Socket和ServerSocket 资源 线程机制
中图分类号:O4文献标识码:A文章编号:1672-7894(2006)12-178-02
一、引言
近年来,IT业在世界范围内迅猛发展,尤其是Internet网的发展更是一日千里,联入了Internet的计算机数迅速增加,各行各业对Internet的依赖性不断地增强,甚至于越来越多的家庭也离不开Internet。
伴随着Internet的发展,也不断出现一些新的技术问题,例如IP地址耗尽、网络资源争用和网络安全等问题。
代理服务器就是为了解决这些问题而产生的一种有效的网络安全产品,并不断地发展。代理服务器(Proxy)是一种中介软件,目的是代替内网的客户端发出资源请求,该请求可以在代理服务器本身得到服务,也可以传向其它服务器。
代理服务器在提高网络资源的利用率、节省网络开销以及网络安全等方面起到了重要作用。
二、HttpProxy的运行机制和实现方法1.关于Jigsaw就Jigsaw本身而言,它是符合HTTP/1.1(RFC2616)标准的WebServer。它具有以下特点:
(1)可移植性,它无需改动就可以运行在任何支持Java的系统平台上;
(2)可扩展性,Jigsaw的可扩展性体现在组成上的扩展和功能的扩展。Jigsaw是由一个内核和一系列扩展模块组成,其中,内核是实现网络联接及网络通信的部分,是Jigsaw的核心组成部分。扩展模块所实现的功能是建立在网络联接及通信之上,如在内核上加上HTTP模块,即可成为WebServer,在内核上加上Proxy模块,即可成为ProxyServer。因此,用户可以编写自己的模块,很方便地将它动态地增加到Jigsaw的内核上,以实现特殊的功能;
(3)面向对象的设计,Jigsaw的设计完全采用面向对象的设计方法,它将所有的资源及服务都作为对象来处理;
(4)Jigsaw工作在开放系统互联(OSI)七层模型的对话层,这与Java中的Socket是一致的,因此,Jigsaw就是利用ServerSocket来提供各类服务。
另外,Jigsaw对资源(Resources)的定义、资源的封装以及提供资源的方式有它独特之处。
(1)有关资源的概念,Jig-saw所定义的资源不仅是包括文件和目录等物理资源,而且还包括虚拟资源,如代理访问的资源等,这不同与其它的WebServer,它们只将CGI脚本或文件当作服务的资源。
(2)Jigsaw对各种原始资源进行两个不同层次的封装,先是对资源本身的封装,如文件资源用FileResource类来对文件进行封装,形成文件资源对象,记录了文件的各类属性。然后,再在封装好的资源上,加载网络信息处理模块。这些模块称为Frame,它是获取不同资源所用到的不同协议,生成Fra-me对象,它包括有传输内容的大小、内容的标识等属性。这样做的好处在于:一是封装后的资源可以使用不同于原始资源名的名称,利用这一名称向外发布该资源,这样就隐藏了物理资源的属性,避免了一些不安全因素。二是对同一个资源来说,可以使用不同的协议或方法来向外发布。
2.将Jigsaw配置成Proxy服务器由于Jigsaw在结构组成上是模块化的,所以,很容易将它配置成代理服务器,具体方法如下:
(1)启动Jigsaw服务器,再启动Jigsaw管理器JigAd-min;
(2)在JigAdmin中,添加一个FramedSouse资源,该资源为虚拟资源;
(3)用ProxyFrame将这个资源封装起来,此时,代理服务器的基本框架就建立起来了;
(4)设置代理的内容,并保存和执行。这样,Jigsaw就成了一个代理服务器。Jigsaw作为代理服务器,它也实现了服务器功能与客户端功能,其中,服务器功能是由它的内核来实现,客户端功能是由ProxyFrame来实现。3.Jigsaw的内核Jigsaw的内核就是一个HttpServer,当Jigsaw启动时,Http服务被创建和初始化,并以线程方式侦听和处理客户端的访问请求。该内核是一个ServerHandlerManager类,主要实现服务器句柄的管理,通过它可初始化和注册了两个服务HttpServer和JigAdmin,并以线程来管理它们。HttpServer的初始化是通过调用Http类中的initialize()函数来实现的,该函数实现了HttpServer的属性设置和服务器端Socket的建立。服务器端Socket的建立代码如下
Private void initializeServerSocket(){
try{Classc=Class.forName(factory_class);factory=(ClientFactory)c.newInstance();//建立一个客户工厂
factory.initialize(this);//初始化客户工厂
}
catch(Exceptionex){…}
try{socket=factory.createServerSocket();//创建一个Ser-verSocket的实例
}
catch(IOException ex){…}this.thread=newThread(this);//创建一个线程,该线程名为Http-Server
this.thread.setName(identifier);this.thread.setPriority(thread.MAX_PRIORITY);}
上述代码中的客户工厂,它负责建立和管理一个线程池,该线程池中容纳了40个空线程,当客户端发来一个请求时,就用其中的一个线程来处理该请求,这样,就实现了多请求的并发处理。当请求多于40个时,多出的请求将不被接受。ServerSocket是Java所提供的一个服务器端的套接字。
套接字(Socket)是现在网络上的两个程序通过一个双向的通信连接实现数据交换的通道,这个双向链路的一端称为一个Socket,服务器端的Socket称为ServerSocket。创建ServerSocket就是建立一个网络连接,其中包括输入数据流和输出数据流。
HttpServer是通过执行Httpd类中的run()函数来实现其服务功能,其代码如下:
Public void run(){…While((!finishing)&&(socket!=null)){Socketns=null;
try{//此socket变量为ServerSocket类型,即初始化过程中建立的
Server socket;
ns=socket.accept();//accept()函数是侦听服务端口的方法;
ns.setTcpNoDelay(true);}catch(IOExceptione){…}If((socket!=null)&&(ns!=null)&&(factory!=null))factory.handleConnection(ns);//处理客户连接
}cleanup(restarting);//若干socket关闭,则清除socket
}
在run()函数中,利用一个循环,不断侦听服务器端口是否有客户请求连接,若有则处理该连接。而这一处理过程是通过调用线程池中的线程来完成。
4.Jigsaw作为Proxy服务器的工作机制当HttpServer侦听到其服务端口上有客户请求,它激活SocketClient类中的run()函数,并用线程池中一个空闲线程来执行它,完成输出缓冲区的建立或重新使用已有的输出缓冲区,调用Client类的startConnection()函数来处理客户请求,最后将本线程从线程池中取消掉。其代码如下:
Public void run(){thread=Thread.currentThread();
…try{//建立输出缓冲区
if(bufout==null){intbufout=getServer().getClientBufferSize()-1;bufout=newSocketOutputBuffer(soc-ket.getOutputStream(),bufsize);}else{bufout.reuse(socket.getOutputStream());}startConnect(newBufferedInputStream(soc-ket.getInputstream)),newdataOutputStream(bufout));//处理客户请求}catch(IOExceptionex){…}}…Client类的startConnection()函数的具体执行过程:(1)建立输入流剖析器,它实现对输入信息的分析,形成符合Http格式的客户请求;(2)执行request=getNextReguest(),从输入流中培析出客户的请求(request);
(3)执行reply=processRequest(request),对客户请求的处理,产生应答(Reply)信息;
(3)通过sent=emitReply(reply),将应答信息转换成数据流格式;
(4)调用output.flush()实现了将当前输出缓冲区中的内容发送给客户;
(5)最后断开连接。处理请求(Request)并形成应答(Reply)过程是由pro-cessRequest()函数来实现的,该函数主要通过调用服务器对象(Httpd类的实例)的perform()函数来完成工作。语句如下:reply=(reply)server.perform(request);
下面介绍httpd类中的perform()函数。该函数实现以一功能:
(1)对所请求的资源进行查找,即执行lookup()函数,返回查找结果,实际上查找结果已包括了客户请求的信息;
(2)执行filter的ingoingFilter()和outgoingFilter()函数,对资源进行封装,改变资源的一些属性,使得访问资源的请求和应答得到过滤。这样通过这一过程,便可得到目标资源,并以Http格式返回。
三、结束语Jigsaw的运行机制和实现,提供了编程实现Http服务和代理服务的方案,对相关的开发与应用都有很大的帮助。
参考文献:[1]Jigsaw文档.[2]RFC2612.[3]王克宏.Java技术教程.清华大学出版社