先简单说下几个概念,根据自己的理解,不正确请见谅。

web服务器

首先要知道什么是web服务器,简单说web服务器就是可以使用HTTP传输协议与客户端进行通信的服务器。最初的web服务器只能用来处理静态页面,而tomcat服务器更加强大,不仅可以处理静态页面,还可以运行java类文件,动态创建页面并返回给浏览器,之所以说tomcat是个容器,就是可以运行servle类的容器,同时可以处理http请求,并返回相应内容。

HTTP协议

http协议是应用层协议,底层使用tcp建立可靠传输连接。所谓协议就是规定了传输内容的规范或格式。先看一个浏览器的http请求:

  


 POST /inner/index.html HTTP/1.1
Host: localhost:
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8 name=ligen&age=21

  

http请求包括三部分:

  1-7行可以归为请求头部分,然后8是空行用以区分实体部分,9行是请求实体内容

  1. (代码1)请求方法--uri--协议/版本
  2. (代码2-7)请求头
  3. (代码9)实体

  第一行POST /inner/index.html HTTP/1.1,POST就是请求方法(还有get等请参考其它),然后是空格;/inner/index.html是请求的资源,一般是相对于根路径的,所以总是以“/”开头;最后是协议和版本。

  http的响应格式与请求类似:

  

 HTTP/1.1  OK
server:tomcat
Content-Type:text/html
Content-Length: <html>
......
</html>

  第一行指定了协议和版本,接着是状态码200,服务器一切运行正常,与请求类似,响应实体部分与信息头部分通过一个空行分隔。

开始建立web服务器

  现在开始着手建立一个简单的web服务器,需要大家有socket基础(了解即可),服务器的基本功能就是基于客户端的请求,建立请求对象request,然后处理相应逻辑找到资源,并封装成response对象通过http将数据传回客户端。因为需要建立三个类:

  • HttpServer 使用socket负责建立服务器,等待客户端连接,建立连接后,根据请求信息初始化Request、Response
  • Request 获取socket的InputStream,封装了客户端的请求信息
  • Response 对应Request的返回信息,获取socket的OutputStream处理返回数据 

(一)HttpServer类

  HttpServer主要建立本地8080端口服务器,等待连接请求,建立请求后使用socket的InputStream和OutputStream分别初始化Request和Response对象。

 public class HttpServer {
pupublic void await() {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
while (true){
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
socket = serverSocket.accept();
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
Request request = new Request(inputStream);//使用连接的inputStream初始化Request
request.Parse();//Parse用于解析原始HTTP请求数据
Response response = new Response(outputStream);
response.setRequest(request);
response.sendStaticResource();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}    

(二)Request类

 public class Request{

     private String uri;
private InputStream in; public Request(InputStream in){
this.in = in;
}
//根据请求头信息获取uri,如GET /index.html HTTP/1.1 ,可以返回/index.html
public String parseUri(String request){
int index1,index2;
index1 = request.indexOf(" ");
if (index1 != -1){
index2 = request.indexOf(" ", index1+ 1);
if (index1 < index2)
return request.substring(index1 + 1, index2);
}
return null;
}
//根据socket的InputStream读取整个字节流,存储在字节数组中,然后使用内存中的字节数组构建StringBUffer对象
public void Parse(){
StringBuffer request = new StringBuffer(2048);
byte[] bs = new byte[2048];
int i;
try {
i = in.read(bs);
} catch (IOException e) {
e.printStackTrace();
i = -1;
} for(int j=0; j<i; j++){
request.append((char)bs[j]);
}
System.out.println(request.toString());
uri = parseUri(request.toString());
} public String getUri() {
return uri;
}
}

(三)Response类

  Response使用socket返回的OutputStream构建对象,setRequest()方法使用初始化后的Request对象出给Response,sendStaticResource()用于发送静态资源,如html文件。

 public class Response implements ServletResponse{

     private static final int BUFFER_SIZE = 1024;
private Request request;
private OutputStream out;
private PrintWriter writer; public Response(OutputStream out) {
this.out = out;
} public void setRequest(Request request) {
this.request = request;
} public void sendStaticResource() throws IOException{
byte[] buffer = new byte[BUFFER_SIZE];
FileInputStream fis = null;
File file = new File(Constant.WEB_ROOT, request.getUri());
try {
fis = new FileInputStream(file);
int ch = fis.read(buffer, 0, BUFFER_SIZE);
while (ch != -1){
out.write(buffer, 0, BUFFER_SIZE);
ch = fis.read(buffer, 0, BUFFER_SIZE);
}
} catch (FileNotFoundException e) {//当文件不存在时,返回错误信息
String html = "<h1>file not found</h1>";
String errorMsg = "HTTP/1.1 404 file not found\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: " + html.getBytes().length + "\r\n" +
"\r\n" +
html;
out.write(errorMsg.getBytes());
}
finally {
if(fis != null){
fis.close();
}
}
}
}

(四)创建MyServer类,启动服务器

 public class MyServer {
public static void main(String[] args) {
HttpServer server = new HttpServer();
server.await();
}
}

理解与模拟一个简单web服务器的更多相关文章

  1. 理解与模拟一个简单servlet容器

    servlet接口 使用servlet编程需要实现或者继承实现了javax.servlet.Servlet接口的类,其中定义了5个签名方法: public void init(ServletConfi ...

  2. 【VB6】vbRichClient5.cWebServer实现一个简单web服务器

    Option Explicit Private WithEvents k As vbRichClient5.cWebServer Private Sub Command1_Click() Set k ...

  3. tomcat解析之简单web服务器(图)

    链接地址:http://gogole.iteye.com/blog/587163 之前有javaeyer推荐了一本书<how tomcat works>,今天晚上看了看,确实不错,第一眼就 ...

  4. 深入理解Tornado——一个异步web服务器

    本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...

  5. C#中使用Socket实现简单Web服务器

    上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...

  6. Socket网络编程--简单Web服务器(1)

    这一次的Socket系列准备讲Web服务器.就是编写一个简单的Web服务器,具体怎么做呢?我也不是很清楚流程,所以我找来了一个开源的小的Web服务器--tinyhttpd.这个服务器才500多行的代码 ...

  7. 写一个简易web服务器、ASP.NET核心知识(4)

    前言 昨天尝试了,基于对http协议的探究,我们用控制台写了一个简单的浏览器.尽管浏览器很low,但是对于http协议有个更好的理解. 说了上面这一段,诸位猜到我要干嘛了吗?(其实不用猜哈,标题里都有 ...

  8. Java 18 新特性:简单Web服务器 jwebserver

    在今年3月下旬的时候,Java版本已经更新到了18.接下来DD计划持续做一个系列,主要更新从Java 9开始的各种更新内容,但我不全部都介绍,主要挑一些有意思的内容,以文章和视频的方式来给大家介绍和学 ...

  9. Socket网络编程--简单Web服务器(6)

    本来是想实现ssl连接的,但是弄了好久都不成功,就索性不做了,等以后有能力再做了.所以这一小节就是本次的最后一节了.就简单的说几个注意点. 1.加个配置文件 使用单例模式,使用一个类,该类保存一些信息 ...

随机推荐

  1. android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!

    目录: 1,过程感慨: 2,运行环境: 3,准备工作: 4,编译 .so 5,遇到的关键问题及其解决方法 6,实现效果截图. ------------------------------------- ...

  2. hdu 1166 敌兵布阵(树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始 ...

  3. jsp入门笔记

    jsp语法 1. declaration 由于访问serlvet只有一个,<%! int i = 0; %>   是servlet的变量,刷新时会不断增加 <% int i = 0; ...

  4. 数据库SQLite

    一.数据库 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等.离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式: 归档:NSKeyedArchiver 偏好设置:NSU ...

  5. javascript练习-方法借用

    方法借用其实也可以叫做多重继承 var generic = { //返回一个字符串,这个字符串包含构造函数的名字(如果构造函数包含名字) //这个以及所有非继承来的,非函数属性的名字和值 toStri ...

  6. XPath使用示例

    1.查找空节点//*[not(text())]        表示内容为空的节点//*[count(*)=0]         表示没有子节点的节点"//*[count(*)=0 and n ...

  7. 读书笔记之深入理解Nginx:模块开发与结构解析

    前言 我现在看书一般都是看自己能看懂的地方,看不懂就先略过,回头再看,下面就写自己看得懂的地方吧,并且把自己的理解也放到里面. 第一部分 Nginx能帮我们做什么 编译安装各个命令解释 configu ...

  8. 使用netty实现的tcp通讯中如何实现同步返回

    在netty实现的tcp通讯中,一切都是异步操作,这提高了系统性能,但是,有时候client需要同步等待消息返回,如何实现呢?笔者已经实现,在此总结下重点要素 实现要点: 1.消息结构设计 消息头中需 ...

  9. Word文字处理器发展演变

    随着信息技术的不断发展,以前书面化的信笺,笔记,书籍以及作业演变成现在不断更新的电子化Word文档. Word是目前世界上最流行.最常用的文字编辑,排版软件,使用它不仅可以提高文档的编辑效率,在修改时 ...

  10. linux定时执行任务crontab命令用法

    linux系统的定时任务是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另外, 由于使用者自己也可以设置计划任务,所 ...