【Jsp精品源码栏目提醒】:网学会员为需要Jsp精品源码的朋友们搜集整理了自己动手写web服务器 - 讲义教程相关资料,希望对各位网友有所帮助!
前几天开始看《How Tomcat Works》因为有人推荐要研究tomcat源代码看这本书是很有帮助的。
看到第三章这几天一直有事也没心情看现在想想别管什么事抽点时间学习学点是点。
为了续得上思路需要把原先的内容在搂一遍。
从浏览器使用者的角度来看我们都知道打开浏览器输入网址URL得到我们想看到的页面。
任何一个web项目开发者都能够想象的出来我们的浏览器和我们访问的网站所在的服务器发生了怎样的勾当。
首先浏览器会根据URLrequest的请求这个请求被服务器上的web服务器接受之后然后返回html文本给浏览器 然后浏览器进行渲染显示。
对于动态web服务器还有一个功能就是把动态如php、
jsp、asp的语言进行解析最后输出html文本。
另外网络基础稍微好一点的开发人员也会知道每一个请求其实就是浏览器想服务器发送了一个http的请求请求格式有以下三部分组成 请求方法URI协议/版本 请求头Request Header 请求正文 例如 GET /index.html HTTP/1.1 Host: localhost:8080 Connection: keep-alive Accept: application/xmlapplication/xhtmlxmltext/htmlq0.9text/plainq0.8image/png/q0.5 User-Agent: Mozilla/5.0 Windows U Windows NT 6.1 AppleWebKit/534.12 KHTML like Gecko Maxthon/3.0 Safari/534.12 Accept-Encoding: gzipdeflate Accept-Language: zh-CN Accept-Charset: iso-8859-1utf-8 另外我们也知道每一个http请求其实就是socket的一次通信socket把请求数据发送到web服务器上。
我们知道浏览器这边大概的活动流程了那么在web服务器那边是怎么运作的呢它是怎么解析我们发过去的数据的它又是如何根据我们发送的请求返回我们需要的资源的 有了这些个疑问要了解并实现一个web服务器就顺其自然了最重要的是有了目的。
根据《How Tomcat Works》第一章我们实现一个简单的WEB服务器。
大致思路如下 1、 首先我们应该监听指定端口如80或者8080或者其他。
2、 在该端口接受到消息之后开始处理。
3、 根据http协议我们可以知道在协议的第一行内容中包含了浏览器请求的资源名称以及路径。
4、 根据浏览器请求的资源找到资源所在然后通过socket输出到浏览器。
根据上面的思路我们首先要有一个类来监听某一端口这个类我们命名为HttpServer.java import java.net.Socket import java.net.ServerSocket import java.net.InetAddress import java.io.InputStream import java.io.OutputStream import java.io.IOException import java.io.File / Listening on the port author the5fire learn tomcat / public class HttpServer / WEB_ROOT is the directory where our HTML and other files reside. For this package WEB_ROOT is the webroot directory under the working directory. The working directory is the location in the file system from where the java command was invoked. / public static final String WEB_ROOT System.getPropertyuser.dir File.separator webroot // shutdown command private static final String SHUTDOWN_COMMAND /SHUTDOWN // the shutdown command received private boolean shutdown false public static void mainString args HttpServer server new HttpServer server.await public void await System.out.printlnWEB_ROOT ServerSocket serverSocket null int port 8080 try serverSocket new ServerSocketport 1 InetAddress.getByName127.0.0.1 catch IOException e e.printStackTrace System.exit1 // Loop waiting for a request while shutdown Socket socket null InputStream input null OutputStream output null try socket serverSocket.accept input socket.getInputStream output socket.getOutputStream // create Request object and parse Request request new Requestinput request.parse // create Response object Response response new Responseoutput response.setRequestrequest response.sendStaticResource // Close the socket socket.close //check if the previous URI is a shutdown command shutdown request.getUri.equalsSHUTDOWN_COMMAND catch Exception e e.printStackTrace continue 另外需要一个Request类来处理服务器的请求以及一个Response来返回消息给客户端。
Request类的具体作用就是根据客户端发送过来的请求然后根据消息的内容得到客户端请求的资源 import java.io.InputStream import java.io.IOException public class Request private InputStream input private String uri public RequestInputStream input this.input input public void parse // Read a set of characters from the socket StringBuffer request new StringBuffer2048 int i byte buffer new byte2048 try i input.readbuffer catch IOException e e.printStackTrace i -1 for int j0 j index1 return requestString.substringindex1 1 index2 return null public String getUri return uri Response类的具体作用就是把Request类解析出来的资源路径读取到程序中然后再输出到客户端 import java.io.OutputStream import java.io.IOException import java.io.FileInputStream import java.io.File / HTTP Response Status-Line general-header response-header entity-header CRLF CRLF message-body Status-Line HTTP-Version SP Status-Code SP Reason-Phrase CRLF / public class Response private static final int BUFFER_SIZE 1024 Request request OutputStream output public ResponseOutputStream output this.output output public void setRequestRequest request this.request request public void sendStaticResource throws IOException byte bytes new byteBUFFER_SIZE FileInputStream fis null try File file new FileHttpServer.WEB_ROOT request.getUri if file.exists fis new FileInputStreamfile int ch fis.readbytes 0 BUFFER_SIZE while ch-1 output.writebytes 0 ch ch fis.readbytes 0 BUFFER_SIZE else // file not found String errorMessage HTTP/1.1 404 File Not Foundrn Content-Type: text/htmlrn Content-Length: 23rn rn File Not Found output.writeerrorMessage.getBytes catch Exception e // thrown if cannot instantiate a File object System.out.printlne.toString finally if fisnull fis.close 然后在你项目所在的路径下面自己建立一个index.html页面里面的内容随便是啥都行然后启动HttpServer这个类在浏览器中输入http://localhost:8080/index.html就能看到你index.html中的内容了。
至此一个简单的静态web服务器就完成了当然现在还是比较简单的也比较简陋因为在httpserver并没有处理如果不是http请求的情况。
不过在这本书的后面这个web服务器会逐渐丰满起来。
大家不妨自己读一下到我网站上方的“
精品书籍下载”中可以下载这本书一个是英文版的是全部。
中文版的只有前四章。
在前一篇文章中通过学习《How Tomcat Works》这本书我们实现了简单的静态WEB服务器今天继续复习下一篇实现一个简单的Servlet服务器。
有了静态服务器实现的基础我们揣测一下Servlet的实现原理不过在此之前我们需要了解什么是Servlet。
关于Servlet的详细定义大家上百科上去看在这里我们只需知道Servlet是一种小的服务器端程序担当客户请求Web浏览器或其他HTTP客户程序与服务器响应HTTP服务器上的数据库或应用程序的中间层。
从上面可知Servlet的主要作用是同http来打交道。
那么我们再来看一个简单的Servlet实现。
import java.io. import javax.servlet.http. import javax.servlet. public class HelloServlet extends HttpServlet public void doGet HttpServletRequest req HttpServletResponse res throws ServletException IOException PrintWriter out res.getWriter out.printlnHello world out.close 看这段代码其中的out.println“Helloworld”显然就是在同http进行交互了。
对比一下我们的静态服务器中的代码会发现静态服务器是通过程序把静态资源输出到客户端而这个Serlvet本身就是程序并且可以输出字符到客户端。
有了这些认识Servlet服务器的实现就变得简单为了让思路变得清晰我们需要uml图来进行辅助。
整个流程就是 从图中我们可以看到Servlet服务器的实现相比于静态服务器其实是多了一个动态加载Servlet的方法然后再执行Servlet。
因为目前是使用javaee包中的Servlet因此还需要将我们原先写的Request类和Response类添加对应的ServletRequest和ServletResponse实现。
具体代码就不在博客上写了感兴趣的话可以自己下载。
TomcatImpl02.src 通过浏览器访问自己的Servlet服务器也可以叫做容器结果截图 这里有一点和《How Tomcat works》书中的不同书上提示说“Note that you cannot see the second string Violets are bluebecause only the first string is flushed to the browser.”。
但是我执行的结果是两条语句都能输出。
不清楚原因在哪某非是Servlet版本的问题。