Tomcat小谈(1)-大神勿喷

问题描述

Tomcat小谈(1)最近闲来无事,就想着研究一些东东,正好想到了上次华为的面试,问了俺一堆堆tomcat的原理性的问题,过程很平淡,结局很惨烈,被完虐,让华为的面试官在我面前秀了一下大神的风采,顿时敬仰之情有如滔滔江水。正好在看论坛的时候,看到了一本我觉的很好的书《HowTomcatWorks》,传说这本书是tomcat研发人员之一写的,本人表示不关心。但是我觉的这本书对tomcat的理解还是很深刻的,于是拿来研究研究。Tomcat最为javaWeb开发者最常用的服务器,我相信90%以上的从业者都用的相当熟练了,且作为开源的Web服务器,器源代码已经公开,但是由于其稍显庞大,当然对于我来讲,是相当庞大,看起来就有些力不从心了。但是从其工作原来将,我们可以仿照她写一个比较简单的,相信动手做了,你对其整个原理会有比较深刻的理解。于是,我在空间把自己的学习经历写下来,以鼓励自己坚持看下去。今天,先来看下一个简单的Web服务器的工作原理。现在的Web通讯是基于HTTP/1.1,我们编写的服务器,就是接受来自浏览器的http请求,最后返回结果给浏览器。先看看HTTP请求和相应的格式。http请求:GET/index.htmlHTTP/1.1Accept:text/html,application/xhtml+xml,*/*Accept-Language:zh-CNUser-Agent:Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;WOW64;Trident/5.0)Accept-Encoding:gzip,deflateHost:127.0.0.1:8080Connection:Keep-Alive

http响应:HTTP/1.1200OKServer:Microsoft-IIS/4.0Date:Mon,5Jan200413:13:33GMTContent-Type:text/htmlLast-Modified:Mon,5Jan200413:13:12GMTContent-Length:112<html><head><title>HTTPResponseExample</title></head><body>WelcometoeastTomcat</body></html>知道了协议,下面动手来写一个简单的web服务器,我分三个类,一个服务器,一个处理Request请求,一个处理Response响应HTTP服务器类:importjava.net.Socket;importjava.net.ServerSocket;importjava.net.InetAddress;importjava.io.InputStream;importjava.io.OutputStream;importjava.io.IOException;importjava.io.File;/***SOCKET服务器**/publicclassHttpServer{/**声明webroot*System.getProperty("user.dir")获取项目跟路径*/publicstaticfinalStringWEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";//关闭服务命令privatestaticfinalStringSHUTDOWN_COMMAND="/SHUTDOWN";//关闭服务接收privatebooleanshutdown=false;publicvoidawait(){ServerSocketserverSocket=null;intport=8080;//声明服务器端口try{InetAddressip=InetAddress.getByName("127.0.0.1");//创建ServerSocketserverSocket=newServerSocket(port,10,//指定客户连接请求队列的长度ip);//通过主机名确定主机的IP地址System.out.println("服务器启动成功:IP"+ip+"端口:"+port);}catch(IOExceptione){e.printStackTrace();System.exit(1);//系统非正常退出}//循环等待客户端while(!shutdown){Socketsocket=null;InputStreaminput=null;OutputStreamoutput=null;try{socket=serverSocket.accept();//阻塞,等待连接input=socket.getInputStream();output=socket.getOutputStream();//创建Request对象,见本包下的Request类Requestrequest=newRequest(input);//向Request中传递inputrequest.parse();//解析URI//创建Response对象,见本包下的Response类Responseresponse=newResponse(output);//向Response中传递outputresponse.setRequest(request);//向Response中传递Requestresponse.sendStaticResource();//调用发送方法//关闭socket,程序进入下一个循环,再次到socket=serverSocket.accept();阻塞处等待连接socket.close();/*检查URL请求中是否有SHUTDOWN_COMMAND命令:如:http://localhost:8080/SHUTDOWN,如果有将变为shutdown为true,循环结束,服务停止*/shutdown=request.getUri().equals(SHUTDOWN_COMMAND);}catch(Exceptione){//e.printStackTrace();//连接发生异常时返回重新等待连接(可能为客户端长时间未操作,连接异常中断等原因,request.getUri()获取null值,无需进行判断,直接重新循环)continue;}}}publicstaticvoidmain(String[]args){HttpServerserver=newHttpServer();server.await();}}Request类importjava.io.InputStream;importjava.io.IOException;/***本例中Request仅用来获取uri**/publicclassRequest{privateInputStreaminput;//定义InputStream存储服务器接收到的InputStreamprivateStringuri;//定义URI,并对外提供get方法publicRequest(InputStreaminput){this.input=input;//构造中初始化input为来自服务器的InputStream}//用来解析HTTP请求信息publicvoidparse(){//创建一个Stringbuffer存储input中的信息StringBufferrequest=newStringBuffer(2048);inti;//接收读取文件长度byte[]buffer=newbyte[2048];try{i=input.read(buffer);//读取input中的流}catch(IOExceptione){e.printStackTrace();i=-1;}for(intj=0;j<i;j++){request.append((char)buffer[j]);//将字节转为char追加在Stringbuffer后面}//获取到http请求,一般组成部分如下,这个可以在浏览器开发模式中看到:/**POST/index.htmlHTTP/1.1Host:127.0.0.1:8080Connection:keep-aliveCache-Control:max-age=0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,;q=0.8User-Agent:Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/34.0.1847.116Safari/537.36Accept-Encoding:gzip,deflate,sdchAccept-Language:zh-CN,zh;q=0.8*/System.out.println(request);uri=parseUri(request.toString());}/*获取URI,在HTTP协议的头部存在这样的结构:方法—统一资源标识符(URI)—协议/版本---如:POST/examples/default.jspHTTP/1.1*所以只要截取前两个空格之间的URL即可*/privateStringparseUri(StringrequestString){intindex1,index2;//存放两个空格的位置index1=requestString.indexOf('');//获取第一个空格的位置if(index1!=-1){index2=requestString.indexOf('',index1+1);//从index1+1位置开始搜索下一个空格的位置if(index2>index1)returnrequestString.substring(index1+1,index2);//返回两个空格间的字符串,即为URI}returnnull;}publicStringgetUri(){returnuri;}}Response类:importjava.io.OutputStream;importjava.io.IOException;importjava.io.FileInputStream;importjava.io.File;/***本类仅处理静态资源**/publicclassResponse{privateRequestrequest;//定义Request对象,用来传递一个Request对象给Response对象privateOutputStreamoutput;//定义OutputStream存储服务器接收到的OutputStreampublicResponse(OutputStreamoutput){this.output=output;//构造中初始化output为来自服务器的OutputStreams}publicvoidsetRequest(Requestrequest){this.request=request;//传递一个Request对象给Response对象}//用来发送一个静态资源publicvoidsendStaticResource()throwsIOException{intBUFFER_SIZE=1024;byte[]bytes=newbyte[BUFFER_SIZE];FileInputStreamfis=null;try{/*创建文件对象,其中HttpServer.WEB_ROOT获取了项目的跟路径+request.getUri()获取的静态资源如:/index.html*/Filefile=newFile(HttpServer.WEB_ROOT,request.getUri());//如果文件存在,向连接方写出文件,(SOCKET中服务器向客户端写出)if(file.exists()){fis=newFileInputStream(file);intch=fis.read(bytes,0,BUFFER_SIZE);//读取文件中一个BUFFERwhile(ch!=-1){output.write(bytes,0,ch);//写出读取到的BUFFERch=fis.read(bytes,0,BUFFER_SIZE);//读取文件中一个BUFFER}}else{//文件如果找不到StringerrorMessage="HTTP/1.1404FileNotFoundrn"+"Content-Type:text/htmlrn"+"Content-Length:23rn"+"rn"+"<h1>404-FileNotFound!</h1>";output.write(errorMessage.getBytes());//向客户端写出一个HTTP响应头,并提示文件找不到}}catch(Exceptione){//如果发生异常,打印次异常信息//output.write(e.toString().getBytes());e.printStackTrace();}finally{if(fis!=null)fis.close();}}}仿照tomcat,在程序的同级目录下建立webroot文件夹,放要访问的资源,上面的代码仅支纯静态html,如,我在webroot下放了一个index.html在浏览器地址栏输入:http://127.0.0.1:8080/index.html即可正常访问运行结果:图片

解决方案

解决方案二:

解决方案三:

解决方案四:
http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/34.gif

时间: 2024-10-21 14:23:11

Tomcat小谈(1)-大神勿喷的相关文章

求助新手大神勿喷,怎样实现缩略图点击后放大,只使用html+css技术!

问题描述 求助新手大神勿喷,怎样实现缩略图点击后放大,只使用html+css技术! 如标题1111111111111111111111111111111111111111 解决方案 只是用html+css实现不了的,需要用到点JavaScript的知识 解决方案二: 为什么不用封装好的呢.我自己用的是fancybox 解决方案三: 配合JS,或者使用CSS3. 使用CSS非常容易实现. 解决方案四: 配合JS,或者使用CSS3. 使用CSS3非常容易实现.

c++-初学C++ 一个小程序 求大神帮忙看下

问题描述 初学C++ 一个小程序 求大神帮忙看下 //分秒显示函数 #include using namespace std; //全局引用std命名空间 void showTime(int ,int); int main() { int hours =0 , mins = 0;//定义且初始化分 和秒 cout << "Input the hour "; cin >> hours; cout << "Input the mins &quo

cocos2d x-Cocos2d-X3.0引入头文件的一个小问题(希望大神帮助)

问题描述 Cocos2d-X3.0引入头文件的一个小问题(希望大神帮助) 假如我现在有一个Player.h的头文件 #include "Player.h"和直接class Player导入有什么区别 问什么我的有的时候#include "Player.h"这样导入会报 (error C2011: "Player":"class"类型重定义)错误 希望大神回答 解决方案 说明你的代码有变量冲突,具体看下错误的行.用命名空间区分下

计算机编程-弱渣问个基础问题。。大神勿笑。。

问题描述 弱渣问个基础问题..大神勿笑.. unicode letter 和 unicode digit 长什么样..能举个例子吗..实在不会 解决方案 新建一个文本文件,输入字母,数字,用unicode保存,然后用ultraedit打开看

acm-ACM的小伙伴进,uva-1584有些小问题求大神解惑

问题描述 ACM的小伙伴进,uva-1584有些小问题求大神解惑 Some DNA sequences exist in circular forms as in the following figure, which shows a circular sequence CGAGTCAGCT", that is, the last symbolT" in CGAGTCAGCT" is connected to the first symbolC". We alway

objective c语法-c语言编程解答数学问题,这是个小问题,大神们来教教我,我只是初学者。。

问题描述 c语言编程解答数学问题,这是个小问题,大神们来教教我,我只是初学者.. 用编程写计算一个矩阵的乘积,关键是循环体内的问题.循环体应该用数组的知识写 解决方案 就是最下面的那个计算矩阵的题.. 解决方案二: 字太小看不清.白天问问你的老师吧. 解决方案三: 大神们快来帮我解决下吧... 解决方案四: 首先初始化:c [i] [j]=0 接着就是矩阵乘,行*列 c[i] [j] = a[i] [k] * b[k] [j] + c[i] [j]

apache+tomcat 启动tomcat 报错 求大神赐教

问题描述 apache+tomcat 启动tomcat 报错 求大神赐教 解决方案 看看org.apache.catalina.filters.CsrfPreventionFilter.jar有没有正确部署. 解决方案二: CsrfPreventionFilter.jar 这个包没有安装吧

tomcat运行出错,大神帮帮忙!

问题描述 tomcat运行出错,大神帮帮忙! HTTP Status 404 - /sheji/file/%E4%BD%9C%E5%93%81%E4%B8%8A%E4%BC%A0.doc type Status report message /sheji/file/%E4%BD%9C%E5%93%81%E4%B8%8A%E4%BC%A0.doc description The requested resource (/sheji/file/%E4%BD%9C%E5%93%81%E4%B8%8A%

java-刚学JAVA有个小问题请教大神~

问题描述 刚学JAVA有个小问题请教大神~ public class Demo2 { public static Void main(String []args) { int a=12; if(a>18) { System.out.println("a>18"); }else if(a>10&&a<=18) { System.out.println("a>10 && a<=18"); }else {