荟聚奇文、博采众长、见贤思齐
当前位置:公文素材库 > 公文素材 > 范文素材 > JavaWeb工作原理

JavaWeb工作原理

网站:公文素材库 | 时间:2019-05-28 14:32:00 | 移动端:JavaWeb工作原理

JavaWeb工作原理

[JavaWeb工作原理][第一章]一什么是JavaWeb?

JavaWeb是用Java技术来解决相关web互联网领域的技术总和。web包括:web服务器和web客户端两部分,在第一个项目(贷款计息查询服务器)的时候已经知道在Web服务器的作用是接受客户端请求,然后向客户端返回一些结果.浏览器的作用是允许用户请求服务器上的某个资源,并且向用户显示请求的结果,HTML用于告诉浏览器怎样向用户显示内容,HTTP是WEB上客户端和服务器之间通信所用的协议

二HTTP协议

Http是一种超文本传输协议(HyperTextTransferProtocol),他是一套计算机在网中通信的一种规则,在TCP/IP体系结构中,HTTP属于应用层协议,位于TCP/IP协议的顶层.HTTP是一种无状态的协议,意思是指在WEB浏览器和WEB服务器之间不需要建立持久的连接,HTTP定义的事物处理由以下四步组成:

1.客户端和WEB服务器建立连接

a)客户端和服务器的连接就是与客户端与服务器的一个TCPSocket套接字连接2.客户端发送HTTP请求

a)请求包含:请求行--请求行是一个ACCII文本行,由请求的HTTP方法,请求的

URL,HTTP版本组成,中间用空格分开,

b)请求头---HTTP协议使用HTTP头来传递请求的元信息,

c)空行---发送回车符和退行,通知服务器以下不再有请求头

d)消息体--HTTP请求中带有查询字符串时,如果是GET方法,查询字符串或表单数据附加在请求行中,那么消息体就没有内容,如果是POST方法,查询字符串或表单数据就添加在消息体重

3.服务器端接收客户端的HTTP请求,生成HTTP相应回发

a)响应包含:状态行---每个HTTP响应以一个状态行开头,它由HTTP协议版本,

响应状态码,响应描述组成,中间用空格分开b)响应头---响应头与请求头一样,也是一个用冒号分隔符的名称/值对,冒号前面

是HTTP头得名称,后面是HTTP头得值c)空行---发送回车符和退行,通知服务器以下不再有响应头

d)消息体---要发送回客户端的HTML文档或其他要显示的内容等,WEB服务器

把要发送给客户端的文档信息放在消息体中

4.服务器端关闭连接,客户端解析并回发响应,恢复页面

a)HTTP响应到达客户端后,浏览器先解析HTTP响应中的状态行,查看请求是否

成功的状态代码,然后开始一步步解析响应

三WEB服务器缺陷与CGI

WEB服务是被设计用来向客户端提供HTTP服务的,它只是能向客户端提供静态网页内容.我们知道,静态网页只是原封不动的待在WEB服务器目录中,服务器知道静态页面,并把它原样传回到客户端,每个客户端看到的页面都是一样的,所以WEB服务器它本身并不具备动态页面,所以在最早有了解决办法CGI,

CGI即通用网关接口(CommonGateWayInterface),是最早用于创建动态服务器端内容的一种技术,使用CGI,WEB服务器可以将客户端的请求传递给一个外部程序,这个外部程序可以执行,创建内容,并且将响应传递给客户端,

但是他在处理一个请求的时候还行,但是在处理对个请求的时候是没有一个用户请求就新开一个进程,我们都知道进程是有独立的内存空间的,如果请求用户多的时候那么就会导致服务器的崩溃,

四Java的解决方案

在java里,Servlet以及web容器,被设计用来解决CGI的问题,为WEB开发者创建一个健壮的服务器环境,

一、Servlet

a)Servlet是J2EE规范,

b)它是一个普通的JAVA类,集成于HttpServlet,用于处理动态页面的响应

c)它是与平台无关的JAVA类,能够编译成平台中立的字节码,从而被基于JAVA技术的WEB服务器动态装载和运行

d)Servlet在服务器端得工作主要是执行如下任务

i.

读取客户端发送的显示和隐式数据

ii.生成结果

iii.向客户端发送显示数据(文档)和隐式数据(HTTP响应数据)

二、WEB容器

a)WEB容器主要是如Tomcat,Jboss,WebLogic,WebSphere,Oracle9iAS等,其中Tomcat是一种用的很广泛的Web容器,它是一个开放源代码的免费的中间件产品b)WEB容器必须对Servlet支持以下几点

i.通信支持

ii.生命周期管理

iii.多线程支持iv.JSP支持v.处理安全性

三、Servlet与WEB容器配合处理请求和响应

a)与GUI类似,Servlet允许一个请求被一个程序处理.并且使用同样的程序产生动态的

响应,此外,Servlet特别定义了一个有效的生命周期,使得用单个进程管理所有请求成为可能,它消除了CGI的多进程缺陷,允许主进程在多个Servlet和多个请求之间共享内存资源.b)Servlet运行在一个主进程或者一个父进程中,每个用户发送请求信息到服务器,就会在Servlet进程里创建一个线程,它们共享一个资源c)最后,WEB容器和Servlet对请求和响应的处理如下

i.客户端向WEB服务器发起一个HTTP请求

ii.HTTP请求被WEB服务器几首,如果请求的是静态页面,则由WEB服务器负责

处理,如果请求的是JAVAWEB组件(Servlet或者JSP),则移交给WEB容器,iii.WEB容器根据Servlet的配置文件(web.xml),确定调用的具体Servlet类,并把request对象,response对象传给它

iv.Servlet通过request对象知道客户端的使用者是谁,客户的请求信息是什么和其

他的一些信息

v.一旦Servlet完成了请求的处理,WEB容器就会刷新response,把控制权返回给

WEB服务器

五JavaWeb应用程序的组成

1.配置文件---每个WEB应用程序包括一个配置文件,WEB.XML2.静态文件和JSP

3.类文件和包---WEB应用程序装载和管理自定义的JAVA代码

4.网页可以放在WEB应用程序的根目录下,根据动态网页或者静态网页放在不同的目

录里

5.图像一般会放在images子目录中,不过这是习惯,不是必须的

6.Servlet类,JavaBean类---编译为Class文件后是防在WEB-INF/classes目录的7.Lib目录用来包含应用程序任何所需要的jar文件8.标记描述其放在WEB-INF目录下

9.Applet程序放在应用的目录下

10.WEB-INF目录下存放web.xml部署描述文件器

剩下的WEB容器Tomcat主要是在实践中应用,在这里不做总结

扩展阅读:JavaWeb工作原理

浅析基于Java的Web服务器工作原理

一个Web服务器也被称为HTTP服务器,它通过HTTP协议与客户端通信。这个客户端通常指的是Web浏览器。一个基于Java的Web服务器用到二个重要的类,java.net.Socket与java.net.ServerSocket,并通过HTTP消息通信。因此,本文从讨论HTTP与这二个类开始,然后我将解释一个与本文相关的简单的Web应用。

TheHypertextTransferProtocol(HTTP)

HTTP是一种让Web服务器与浏览器(客户端)通过Internet发送与接收数据的协议。它是一个请求、响应协议--客户端发出一个请求,服务器响应这个请求。HTTP运用可靠的TCP连接,通常用的TCP80端口。它的第一个版本是HTTP/0.9,然后被HTTP/1.0取代。当前的版本是HTTP/1.1,由RFC2616(.pdf)定义。

本节主要对应HTTP1.1,足够使你充分理解由Web服务器程序发出的消息。如果你对更加详细的知识有兴趣,可以参考RFC2616。

在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回叫连接。客户端与服务器端都可以提前中断一个连接。例如,当用一个浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的HTTP连接。

HTTP请求

一个HTTP请求包含三个部分:

Method-URI-Protocol/Version方法-地址-版本

Requestheader请求头

Entitybody请求实体

下面是一个HTTP请求实例:

POST/servlet/default.jspHTTP/1.1

Accept:text/plain;text/htmlAccept-Language:en-gb

Connection:Keep-Alive

Host:localhost

Referer:

User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)

Content-Length:33

Content-Type:application/x-www-form-urlencoded

Accept-Encoding:gzip,deflate

LastName=Franks&FirstName=Michael

TheMethod-URI-Protocol/Version在这个请求的第一行:

POST/servlet/default.jspHTTP/1.1

其中POST是请求的类型。每个客户端HTTP请求可以是HTTP规范中指定的许多请求类型中的一种。HTTP1.1支持七种类型的请求,它们是GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE。其中GET与POST是Internet应用中经常用到的二种请求类型。

URI完整地指定了Internet资源。一个URI通常被解析为相对服务器的根目录。这样,它应该总是以一个"/"前缀开始。一个URL实际上是URI的一种类型。

Version指的是该HTTP请求所用到的HTTP协议版本。

请求头包含了客户端环境与请求实体的一些有用的信息。例如它包含浏览器设定的语言、实体的长度等等。每条请求头用回车换行符(CRLF)分开。一个非常重要的空行分开了请求头与实体,它标志着实体内容的开始。一些Internet开发书籍认为这个CRLF空行是HTTP请求的第四个部分。

在上面的HTTP请求中,实体只是简单以下的一行:

LastName=Franks&FirstName=Michael

在一个典型的HTTP请求中,请求实体内容会长得多。

HTTP响应

与请求相似,HTTP响应也由三部分组成:

Protocol-Statuscode-Description协议状态描述代码

Responseheaders响应头

Entitybody响应实体

以下是一个HTTP响应的实例:

HTTP/1.1200OK

Server:Microsoft-IIS/4.0

Date:Mon,3Jan199813:13:33GMT

Content-Type:text/html

Last-Modified:Mon,11Jan199813:23:42GMT

Content-Length:1

WelcometoBrainySoftware

响应头的第一行类似请求头的第一行,告诉你所用的协议是HTTP1.1,请求成功(200=success),以及没有任何问题。

响应头类似请求头也包含了一些有用的信息。响应的实体响应本身的HTML内容。头与实体之间由回车换行的空行(CRLF)分开。

Socket类

一个socket是一个网络连接的端点,它使得一个应用可以从网络读与写。在不同电脑上的二个应用软件能够通过收发字节流而彼此通信。要发一个信息到另一个应用程序,你需要知道它的IP地址,以及它的socket端口号。在Java中,一个socket用java.net.Socket来实现。

要创建一个socket,你可以用Socket类中几个构建方法中的一个。其中一个接受主机名与端口号作为参数:

newSocket("yahoo.com",80);

一旦你成功地创建了一个Socket类的实例,你就可以用它去发送与接收字节流了。要发送字节流,你需要呼叫Socket类的getOutputStream方法来得到一个java.io.OutputSteam对象。要发送文本到远程的程序,你通常需要从返回的OutputStream创建一个java.io.PrintWriter对象。要从连接的另一端接收字节流,你需要呼叫Socket类的getInputStream方法,它返回一个java.io.InputStream对象。

以下代码创建一个可以与本地HTTP服务器通信的socket(127.0.0.1表示一个本地的主机),发送一个HTTP请求,并接收从服务器的响应。它还创建一个StringBuffer对象来接受响应,并打印到控制台。

Socketsocket=newSocket("127.0.0.1","8080");OutputStreamos=socket.getOutputStream();

booleanautoflush=true;

PrintWriterout=newPrintWriter(socket.getOutputStream(),

autoflush);

BufferedReaderin=newBufferedReader(

newInputStreamReader(socket.getInputStream()));

//sendanHTTPrequesttothewebserver

out.println("GET/index.jspHTTP/1.1");

out.println("Host:localhost:8080");

out.println("Connection:Close");

out.println();

//readtheresponse

booleanloop=true;

StringBuffersb=newStringBuffer(8096);

while(loop){

if(in.ready()){inti=0;

while(i!=-1){

i=in.read();

sb.append((char)i);}

loop=false;}

Thread.currentThread().sleep(50);}

//displaytheresponsetotheoutconsole

System.out.println(sb.toString());

socket.close();

注意要从web服务器得到正确的响应,你必须要发送用HTTP协议编译了的HTTP请求。如果你看了上面的HTTP部分,你应该能够理解上面代码中的HTTP请求。

编者注:这篇文章节选自budi自己出版的书<Tomcat内幕>。你可以在他的网站得到更多的相关资料。

基于Java的Web服务器工作原理2

作者:fajaven译发文时间:201*.09.1217:00:38

ServerSocket类

Socket类描述的是“客户端”socket,当你需要创建与远程服务程序连接时需要用到它。如果你想实现一个服务程序,如HTTP服务器或者FTP服务器,则需要另外不同的方法。这是因为你的服务器必须随时服务,它不知道什么时候会有一个客户端程序需要连接它。

因为这个目的,你需要用到java.net.ServerSocket这个类,它是服务器端socket的一个实现。服务器端socket等待来自客户端的连接请求。一旦它收到一个连接请求,它创建一个socket实例来与客户端进行通信。

要创建服务器端socket,需要用到ServerSocket类提供的四个构建方法中的一个。你需要指定服务器端socket侦听的IP地址与端口号。比较典型地,这个IP地址可以是127.0.0.1,意思是该服务器端socket侦听的是本地机器。服务器端socket侦听的IP地址指的是绑定地址。服务器端socket另一个重要的属性是队列长度,即它拒绝请求前所接受的最大请求排队长度。

ServerSocket类的构建方法之一如下:

publicServerSocket(intport,intbackLog,InetAddressbindingAddress);

对于这个构建方法,绑定地址必须是java.net.InetAddress类的实例。创建一个InetAddress类的对象的简单方法是呼叫其静态方法getByName,传递一个包含主机名的字符串。

InetAddress.getByName("127.0.0.1");

以下行的代码创建了一个服务器端socket,它侦听本地机器的8080端口,限制队列长度为1。

newServerSocket(8080,1,InetAddress.getByName("127.0.0.1"));

一旦有了一个ServerSocket实例,就可以通过呼叫其accept方法来让它等待进来的链接请求。这个方法只有当接收到请求时才返回,它返回的是Socket类的实例。这个Socket对象就可以用来从客户端应用程序发送与接收字节流,正如上节据说的那样。实际上,accept方法是本文例子中用到的唯一方法。

应用实例

我们的web服务器程序是ex01.pyrmont包的一部分,它包含三个类:HttpServer;Request;Response。

整个程序的入口(静态main方法)是HttpServer类。它创建一个HttpServer的实例,并呼叫其await方法。正如名字表达的,await在一个特定的端口等待HTTP请求,处理它们,并返回响应给客户端。它保持等待状态,直到收到停止命令。(用方法名await代替wait,是因为System中有一个重要的与线程相关的方法)

这个程序只从一个特定的目录发送静态资源,如HTML与图像文件。它只支持没有文件头(如日期与cookie)的情况。现在我们将在如下的几节中看一下这三个类。

HttpServer类

HttpServer实现了一个web服务器,它可以提供(serve)特定目录及其子目录下的静态资源。这个特定的目录由publicstaticfinalWEB_ROOT指定。

WEB_ROOT初始化如下:

publicstaticfinalStringWEB_ROOT=

System.getProperty("user.dir")+File.separator+"webroot";

代码列表中包含了一具叫做webroot的目录,里面有一些静态的资源,你可以用来测试本应用。你也可以看到一个servlet,在我的下一篇文章将会被用到:“Servlets容器是怎样工作的”。

为了请求一个静态的资源,在浏览器的地址栏输入如是地址::port/staticResources

如果你从不同的机器上发送请求到运行本应用的机器,则machinename是运行应用机器的机器名或IP地址,port是8080,staticResources是被请求的文件名称,它必须包含在WEB_ROOT目录内。

例如,如果你用同一台电脑来测试这个应用,你想要HttpServer发送index.html这个文件,用以下的地址::8080/index.html

要停止服务,只需要从浏览器发送一个停止(shutdown)命令,即在浏览器的地址栏输入host:port字段后,加上预先定义好的字符串。在我们的HttpServer类中,停止命令被定义为SHUTDOWN,一个staticfinal变量。

privatestaticfinalStringSHUTDOWN_COMMAND="/SHUTDOWN";

因此,要停止服务,你可以这样::8080/SHUTDOWN现在,让我们看一下列表1.1中给出的await方法。代码列表后面将对这段代码做一些解释。

Listing1.1.TheHttpServerclass"awaitmethod

publicvoidawait(){

ServerSocketserverSocket=null;

intport=8080;try{

serverSocket=newServerSocket(port,1,

InetAddress.getByName("127.0.0.1"));}

catch(IOExceptione){

e.printStackTrace();

System.exit(1);}

//Loopwaitingforarequest

while(!shutdown){

Socketsocket=null;

InputStreaminput=null;

OutputStreamoutput=null;try{

socket=serverSocket.accept();

input=socket.getInputStream();

output=socket.getOutputStream();

//createRequestobjectandparse

Requestrequest=newRequest(input);

request.parse();

//createResponseobject

Responseresponse=newResponse(output);

response.setRequest(request);

response.sendStaticResource();

//Closethesocket

socket.close();

//checkifthepreviousURIisashutdowncommand

shutdown=request.getUri().equals(SHUTDOWN_COMMAND);}

catch(Exceptione){

e.printStackTrace();

continue;}}}

await方法以创建一个ServerSocket实例开始,然后进入一个while的循环。

serverSocket=newServerSocket(

port,1,InetAddress.getByName("127.0.0.1"));...

//Loopwaitingforarequest

while(!shutdown){...}

在while循环中的代码,运行到ServerSocket的accept方法即停止。这个方法只有在8080端口接收到HTTP请求才返回:

socket=serverSocket.accept();

收到请求后,await方法从accept方法返回的Socket实例中等到java.io.InputStream与java.io.OutputStream:

input=socket.getInputStream();

output=socket.getOutputStream();

然后await方法创建一个Request对象,呼叫它的parse方法来解析这个原始的HTTP请求:

//createRequestobjectandparse

Requestrequest=newRequest(input);

request.parse();

下一步,await方法创建一个Response对象并把Request对象设置给它,呼叫它的sendStaticResource方法:

//createResponseobject

Responseresponse=newResponse(output);

response.setRequest(request);

response.sendStaticResource();

最后,await方法关闭Socket,呼叫Request的getUri方法来检查HTTP请求的地址是否是一个停止命令。如果是,则shutdown变量被设置为true,程序退出while循环:

//Closethesocket

socket.close();

//checkifthepreviousURIisashutdowncommand

shutdown=request.getUri().equals(SHUTDOWN_COMMAND);

基于Java的Web服务器工作原理3

作者:fajaven发文时间:201*.09.1217:11:54

Request类

Request类对应HTTP请求。创建这个类的实例,并传给它从Socket获得的InputStream对象,从而捕获与客户端的通信。呼叫InputStream对象的read方法中的一个就可以得到HTTP请求的原始数据。

Request类有二个public方法parse与getUri。parse方法解析HTTP请求的原始数据。它做的事情不多--唯一它使之有效的信息是HTTP请求的URI,这个通过呼叫私有方法parseUri来获得。parseUri方法把URI作为一个变量。调用getUri方法可以得到HTTP请求的URI。

要明白parse与parseUri的工作原理,你需要知道HTTP请求的结构,由RFC2616定义。

一个HTTP请求包括三个部分:Requestline;Headers;Messagebody。

现在,我们只需要关注HTTP请求的第一部分--请求行。请求行以方法记号开始,接着是请求的URI与协议版本,以回车换行符结束。请求行的元素之间以空格分开。例如,一个用GET方法的index.html文件的请求行如下:

GET/index.htmlHTTP/1.1

parse方法从socket的InputStream传递给Request对象中读取字节流,把这个字节数组存在缓冲里。然后,它把buffer字节数组里的字节放入叫做request的StringBuffer对象中,再把StringBuffer替换成String传递给parseUri方法。

parse方法的代码如列表1.2

Listing1.2.TheRequestclass"parsemethod

publicvoidparse(){

//ReadasetofcharactersfromthesocketStringBufferrequest=newStringBuffer(2048);inti;

byte[]buffer=newbyte[2048];try{

i=input.read(buffer);}

catch(IOExceptione){

e.printStackTrace();i=-1;}

for(intj=0;jrequest.append((char)buffer[j]);}

System.out.print(request.toString());

uri=parseUri(request.toString());}

parseUri方法查找请求行的第一个与第二个空格,从而从请求行获得了URI。列表1.3展示了parseUri方法的代码。

Listing1.3.TheRequestclass"parseUrimethod

privateStringparseUri(StringrequestString){intindex1,index2;

index1=requestString.indexOf("");

if(index1!=-1){

index2=requestString.indexOf("",index1+1);

if(index2>index1)

returnrequestString.substring(index1+1,index2);}

returnnull;}

Response类

Response类描述HTTP响应。它的构建方法接受OutputStream对象,如下:

publicResponse(OutputStreamoutput){

this.output=output;}

Response对象通过传递从socket获得的OutputStream对象到HttpServer类的await方法而创建。

Response类有二个公共方法setRequest与setStaticResource。setRequest用来传递Request对象到Response对象。它比较简单,代码如列表1.4所示:

Listing1.4.TheResponseclass"setRequestmethod

publicvoidsetRequest(Requestrequest){

this.request=request;}

sendStaticResource方法用来发送静态的资源,例如HTML文件。它的实现如列表1.5所示:

Listing1.5.TheResponseclass"sendStaticResourcemethod

publicvoidsendStaticResource()throwsIOException{

byte[]bytes=newbyte[BUFFER_SIZE];

FileInputStreamfis=null;try{

Filefile=newFile(HttpServer.WEB_ROOT,request.getUri());

if(file.exists()){

fis=newFileInputStream(file);

intch=fis.read(bytes,0,BUFFER_SIZE);

while(ch!=-1){

output.write(bytes,0,ch);

ch=fis.read(bytes,0,BUFFER_SIZE);}}else{

//filenotfound

StringerrorMessage="HTTP/1.1404FileNotFound\\r\\n"+

"Content-Type:text/html\\r\\n"+

"Content-Length:23\\r\\n"+"\\r\\n"+"

FileNotFound";

output.write(errorMessage.getBytes());}}

catch(Exceptione){

//thrownifcannotinstantiateaFileobject

System.out.println(e.toString());}finally{

if(fis!=null)

fis.close();}}

SendStaticResource方法非常简单。它首先通过传递父与子目录到File类的构建方法从而实例化java.io.File类。

FilefilenewFile(HttpServer.WEB_ROOT,request.getUri());

然后检查这个文件是否存在。如果存在,则sendStaticResource方法传递File对象创建java.io.FileInputStream对象。然后调用FileInputStream的read方法,并把字节数组写到OutputStream对象output。就这样,静态资源的内容作为原始数据被发送到浏览器。

if(file.exists()){

fis=newFileInputStream(file);

intch=fis.read(bytes,0,BUFFER_SIZE);

while(ch!=-1){

output.write(bytes,0,ch);

ch=fis.read(bytes,0,BUFFER_SIZE);}}

如果文件不存在,sendStaticResource发送一个错误信息到浏览器。

StringerrorMessage="HTTP/1.1404FileNotFound\\r\\n"+

"Content-Type:text/html\\r\\n"+

"Content-Length:23\\r\\n"+"\\r\\n"+"

FileNotFound";

output.write(errorMessage.getBytes());

编译与运行应用程序

要编辑与运行本文的应用,首先你需要解压源码zip文件。直接解压出来的目录被称为工作目录,它有三个子目录:src/,classes/,lib/。要编译应用,从工作目录输入如下命令:

javac-d.src/ex01/pyrmont/*.java

-d选项把结果写到当前目录,而不是src/目录。

要运行应用,在当前工作目录输入如下命令:

javaex01.pyrmont.HttpServer

测试这个应用,打开你的浏览器,在地址栏输入如下地址::8080/index.html

你将在你的浏览器看到index.html显示出来,如图1所示。

图1:web服务器的输出显示

在控制台,你看到如下的内容:

GET/index.htmlHTTP/1.1

Accept:*/*Accept-Language:en-us

Accept-Encoding:gzip,deflate

User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)

Host:localhost:8080

Connection:Keep-Alive

GET/images/logo.gifHTTP/1.1

Accept:*/*

Referer::8080/index.html

Accept-Language:en-us

Accept-Encoding:gzip,deflate

User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)

Host:localhost:8080

Connection:Keep-Alive总结

在这篇文章中(分为三个部分),你看到了一个简单的web服务器的工作原理。本文相关的应用只包括了三个类,功能是不全面的。然而,它仍不失为一个好的学习工具。

(责任编辑:张明燕)

Java的网络编程:用Java实现Web服务器

作者:谷和启发文时间:201*.12.2615:35:57

HTTP协议

超文本传输协议(HTTP)是位于TCP/IP协议的应用层,是最广为人知的协议,也是互连网中最核心的协议之一,同样,HTTP也是基于C/S或B/S模型实现的。事实上,我们使用的浏览器如Netscape或IE是实现HTTP协议中的客户端,而一些常用的Web服务器软件如Apache、IIS和iPlanetWebServer等是实现HTTP协议中的服务器端。Web页由服务端资源定位,传输到浏览器,经过浏览器的解释后,被客户所看到。

Web的工作基于客户机/服务器计算模型,由Web浏览器(客户机)和Web服务器(服务器)构成,两者之间采用超文本传送协议(HTTP)进行通信。HTTP协议是Web浏览器和Web服务器之间的应用层协议,是通用的、无状态的、面向对象的协议。

一个完整的HTTP协议会话过程包括四个步骤:

◆连接,Web浏览器与Web服务器建立连接,打开一个称为Socket(套接字)的虚拟文件,此文件的建立标志着连接建立成功;

◆请求,Web浏览器通过Socket向Web服务器提交请求。HTTP的请求一般是GET或POST命令(POST用于FORM参数的传递);

◆应答,Web浏览器提交请求后,通过HTTP协议传送给Web服务器。Web服务器接到后,进行事务处理,处理结果又通过HTTP传回给Web浏览器,从而在Web浏览器上显示出所请求的页面;

◆关闭连接,应答结束后Web浏览器与Web服务器必须断开,以保证其它Web浏览器能够与Web服务器建立连接。

Java实现Web服务器功能的程序设计

编程思路

根据上述HTTP协议的会话过程,本实例中实现了GET请求的Web服务器程序的方法,方法如下:

通过创建ServerSocket类对象,侦听用户指定的端口(为8080),等待并接受客户机请求到端口。创建与Socket相关联的输入流和输出流,然后读取客户机的请求信息。若请求类型是GET,则从请求信息中获取所访问的HTML文件名;如果HTML文件存在,则打开HTML文件,把HTTP头信息和HTML文件内容通过Socket传回给Web浏览器,然后关闭文件,否则发送错误信息给Web浏览器。最后关闭与相应Web浏览器连接的Socket。

用Java编写Web服务器httpServer.java文件的源代码如下:

//httpServer.java

importjava.net.*;

importjava.io.*;

importjava.util.*;

importjava.lang.*;

publicclasshttpServer{

publicstaticvoidmain(Stringargs[]){intport;

ServerSocketserver_socket;

//读取服务器端口号try{

port=Integer.parseInt(args[0]);}

catch(Exceptione){

port=8080;}try{

//监听服务器端口,等待连接请求

server_socket=newServerSocket(port);

System.out.println("httpServerrunningonport"+

server_socket.getLocalPort());

//显示启动信息

while(true){

Socketsocket=server_socket.accept();

System.out.println("Newconnectionaccepted"+

socket.getInetAddress()+

":"+socket.getPort());

//创建分线程try{

httpRequestHandlerrequest=

newhttpRequestHandler(socket);

Threadthread=newThread(request);

//启动线程

thread.start();}

catch(Exceptione){

System.out.println;}}}

catch(IOExceptione){

System.out.println;}}}

classhttpRequestHandlerimplementsRunnable{

finalstaticStringCRLF="\\r\\n";

Socketsocket;

InputStreaminput;

OutputStreamoutput;

BufferedReaderbr;

//构造方法

publichttpRequestHandler(Socketsocket)throwsException{

this.socket=socket;

this.input=socket.getInputStream();

this.output=socket.getOutputStream();

this.br=

newBufferedReader(newInputStreamReader(socket.getInputStream()));}

//实现Runnable接口的run()方法

publicvoidrun(){try{

processRequest();}

catch(Exceptione){

System.out.println;}}

privatevoidprocessRequest()throwsException{

while(true){

//读取并显示Web浏览器提交的请求信息

StringheaderLine=br.readLine();

System.out.println("Theclientrequestis"+headerLine);

if(headerLine.equals(CRLF)||headerLine.equals(""))break;

StringTokenizers=newStringTokenizer(headerLine);

Stringtemp=s.nextToken();

if(temp.equals("GET")){

StringfileName=s.nextToken();

fileName="."+fileName;

//打开所请求的文件

FileInputStreamfis=null;

booleanfileExists=true;try{

fis=newFileInputStream(fileName);}

catch(FileNotFoundExceptione){

fileExists=false;}

//完成回应消息

StringserverLine="Server:asimplejavahttpServer";

StringstatusLine=null;

StringcontentTypeLine=null;

StringentityBody=null;

StringcontentLengthLine="error";

if(fileExists){

statusLine="HTTP/1.0200OK"+CRLF;

contentTypeLine="Content-type:"+

contentType(fileName)+CRLF;

contentLengthLine="Content-Length:"

+(newInteger(fis.available())).toString()

+CRLF;}else{

statusLine="HTTP/1.0404NotFound"+CRLF;

contentTypeLine="text/html";

entityBody=""+""+

"404NotFound"+"

usage::port/"

+"fileName.html";}

//发送到服务器信息

output.write(statusLine.getBytes());

output.write(serverLine.getBytes());

output.write(contentTypeLine.getBytes());

output.write(contentLengthLine.getBytes());

output.write(CRLF.getBytes());//发送信息内容

if(fileExists){

sendBytes(fis,output);

fis.close();}else{

output.write(entityBody.getBytes());}}}

//关闭套接字和流try{

output.close();

br.close();

socket.close();}

catch(Exceptione){}}

privatestaticvoidsendBytes(FileInputStreamfis,OutputStreamos)

throwsException{

//创建一个1Kbuffer

byte[]buffer=newbyte[1024];

intbytes=0;

//将文件输出到套接字输出流中

while((bytes=fis.read(buffer))!=-1){

os.write(buffer,0,bytes);}}

privatestaticStringcontentType(StringfileName){

if(fileName.endsWith(".htm")||fileName.endsWith(".html")){

return"text/html";}

return"fileName";}}

编程技巧说明◆主线程设计

主线程的设计就是在主线程httpServer类中实现了服务器端口的侦听,服务器接受一个客户端请求之后创建一个线程实例处理请求,代码如下:

importjava.net.*;

importjava.io.*;

importjava.util.*;

importjava.lang.*;

publicclasshttpServer{

publicstaticvoidmain(Stringargs[]){port;

ServerSocketserver_socket;

//读取服务器端口号try{

port=Integer.parseInt(args[0]);}

catch(Exceptione){

port=8080;}try{

//监听服务器端口,等待连接请求

server_socket=newServerSocket(port);

System.out.println("httpServerrunningonport"

+server_socket.getLocalPort());....................

◆连接处理分线程设计

在分线程httpRequestHandler类中实现了HTTP协议的处理,这个类实现了Runnable接口,代码如下:

classhttpRequestHandlerimplementsRunnable{

finalstaticStringCRLF="\\r\\n";

Socketsocket;

InputStreaminput;

OutputStreamoutput;

BufferedReaderbr;

//构造方法

publichttpRequestHandler(Socketsocket)throwsException{

this.socket=socket;

//得到输入输出流

this.input=socket.getInputStream();

this.output=socket.getOutputStream();

this.br=

newBufferedReader(newInputStreamReader(socket.getInputStream()));}

//实现Runnable接口的run()方法

publicvoidrun(){try{

processRequest();}

catch(Exceptione){

System.out.println;}}

◆构建processRequest()方法来处理信息的接收和发送

作为实现Runnable接口的主要内容,在run()方法中调用processRequest()方法来处理客户请求内容的接收和服务器返回信息的发送,代码如下:

privatevoidprocessRequest()throwsException{

while(true){

//读取并显示Web浏览器提交的请求信息

StringheaderLine=br.readLine();

System.out.println("Theclientrequestis"+headerLine);

if(headerLine.equals(CRLF)||headerLine.equals(""))break;

//根据请求字符串中的空格拆分客户请求

StringTokenizers=newStringTokenizer(headerLine);

Stringtemp=s.nextToken();

if(temp.equals("GET")){

StringfileName=s.nextToken();

fileName="."+fileName;

.............

.............

在processRequest()方法中得到客户端请求后,利用一个StringTokenizer类完成了字符串的拆分,这个类可以实现根据字符串中指定的分隔符(缺省为空格)将字符串拆分成为字串的功能。利用nextToken()方法依次得到这些字串;sendBytes()方法完成信息内容的发送,contentType()方法用于判断文件的类型。

显示Web页面

显示Web页面的index.html文件代码如下:

*********欢迎你的到来!*********

这是一个用Java语言实现的Web服务器

--------------------------------------------------------------------------------

运行实例

为了测试上述程序的正确性,将编译后的httpServer.class、httpRequestHandler.class和上面的index.html文件置于网络的某台主机的同一目录中。

首先运行服务器程序javahttpServer8080,服务器程序运行后显示端口信息“httpServerruningonport8080”,然后在浏览器的地址栏中输入:8080/index.html,就可以正确显示网页,同时在显示“httpServerruningonport8080”窗口中服务器会出现一些信息。

友情提示:本文中关于《JavaWeb工作原理》给出的范例仅供您参考拓展思维使用,JavaWeb工作原理:该篇文章建议您自主创作。

来源:网络整理 免责声明:本文仅限学习分享,如产生版权问题,请联系我们及时删除。


JavaWeb工作原理》由互联网用户整理提供,转载分享请保留原作者信息,谢谢!
链接地址:http://www.bsmz.net/gongwen/585498.html
相关文章