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

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. swift的运算符

    1.什么是运算符?它有什么作用? 运算符是一种特定的符号或者表达式.它用来验证.修改.合并变量. 2.运算符有哪些? 运算符有很多,很多朋友学的很烦.这里我依据它的作用把它分为几块来介绍: a:赋值运 ...

  2. XStream学习笔记

    XStream 所需jar包: xstream-1.3.jar xpp3_min-1.1.4c.jar xmlpull-1.1.3.1.jar 目录: 1.注解去除,标签中带有包名的节点 2.注解修改 ...

  3. (转)JQuery上传插件Uploadify使用详解

    原文地址:http://www.cnblogs.com/oec2003/archive/2010/01/06/1640027.html Uploadify是JQuery的一个上传插件,实现的效果非常不 ...

  4. MSSQL数据库中Text类型字段在PHP中被截断之解 (转)

    在PHP中使用了MSSQL数据库,恰巧数据库中又使用了Text类型字段,于是问题产生了.每次从数据库中查询得到的数据总是被莫名的截断,一开始是以为我使用的PHP框架中对字符串的长度有所限制,后来发现这 ...

  5. 【转】java.lang.OutOfMemoryError: Java heap space的解决

    原文地址:http://blog.sina.com.cn/s/blog_4b12778b0100v0bb.html Myeclipse下java.lang.OutOfMemoryError: Java ...

  6. 关于提高webview里下载apk安装包成功率的研究

    移动互联网发展到当下,各种领域出现了一些大的app平台,这些app共同的特点就是拥有大量忠实活跃用户, 要知道,有用户就有money啊~ 于是乎其他不太知名的平台,开始在他们上面疯狂投放广告,做活动推 ...

  7. 使用阿里云负载均衡遭遇的http重定向https的问题

    昨天解决了在阿里云负载均衡上部署https证书的问题(详见一个空行引起的阿里云负载均衡上部署https证书的问题),并完成了部署,负载均衡的监听配置是这样的: 用户与负载均衡之间走https协议,负载 ...

  8. ENode 2.0 - 介绍一下关于ENode中对Command的调度设计

    CQRS架构,C端的职责是处理从上层发送过来的command.对于单台机器来说,我们如何尽快的处理command呢?本文想通过不断提问和回答的方式,把我的思考写出来. 首先,我们最容易想到的是使用多线 ...

  9. Aoite 系列(04) - 强劲的 CommandModel 开发模式(上篇)

    Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.CommandModel 是一种开发模式,我把它成为"命令模型",这是一 ...

  10. 团队项目——站立会议DAY12

    第十二次站立会议记录: 参会人员:张靖颜,钟灵毓秀,何玥,赵莹,王梓萱 项目进展: 1.张靖颜:已经将部分代码完成,对一些模块化的功能进行扩展,对已具备的功能进行完善. 2.钟灵毓秀:对代码进行了修改 ...