先简单说下几个概念,根据自己的理解,不正确请见谅。
首先要知道什么是web服务器,简单说web服务器就是可以使用HTTP传输协议与客户端进行通信的服务器。最初的web服务器只能用来处理静态页面,而tomcat服务器更加强大,不仅可以处理静态页面,还可以运行java类文件,动态创建页面并返回给浏览器,之所以说tomcat是个容器,就是可以运行servle类的容器,同时可以处理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)请求方法--uri--协议/版本
- (代码2-7)请求头
- (代码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服务器,需要大家有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服务器的更多相关文章
-
理解与模拟一个简单servlet容器
servlet接口 使用servlet编程需要实现或者继承实现了javax.servlet.Servlet接口的类,其中定义了5个签名方法: public void init(ServletConfi ...
-
【VB6】vbRichClient5.cWebServer实现一个简单web服务器
Option Explicit Private WithEvents k As vbRichClient5.cWebServer Private Sub Command1_Click() Set k ...
-
tomcat解析之简单web服务器(图)
链接地址:http://gogole.iteye.com/blog/587163 之前有javaeyer推荐了一本书<how tomcat works>,今天晚上看了看,确实不错,第一眼就 ...
-
深入理解Tornado——一个异步web服务器
本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...
-
C#中使用Socket实现简单Web服务器
上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...
-
Socket网络编程--简单Web服务器(1)
这一次的Socket系列准备讲Web服务器.就是编写一个简单的Web服务器,具体怎么做呢?我也不是很清楚流程,所以我找来了一个开源的小的Web服务器--tinyhttpd.这个服务器才500多行的代码 ...
-
写一个简易web服务器、ASP.NET核心知识(4)
前言 昨天尝试了,基于对http协议的探究,我们用控制台写了一个简单的浏览器.尽管浏览器很low,但是对于http协议有个更好的理解. 说了上面这一段,诸位猜到我要干嘛了吗?(其实不用猜哈,标题里都有 ...
-
Socket网络编程--简单Web服务器(6)
本来是想实现ssl连接的,但是弄了好久都不成功,就索性不做了,等以后有能力再做了.所以这一小节就是本次的最后一节了.就简单的说几个注意点. 1.加个配置文件 使用单例模式,使用一个类,该类保存一些信息 ...
-
用nodejs搭建一个简单的服务器
使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...
随机推荐
-
Java 7 Fork/Join 并行计算框架概览
应用程序并行计算遇到的问题 当硬件处理能力不能按摩尔定律垂直发展的时候,选择了水平发展.多核处理器已广泛应用,未来处理器的核心数将进一步发布,甚至达到上百上千的数量.而现在 很多的应用程序在运行在多核 ...
-
c语言,动态数组
试着直接malloc一个2*3*4的空间来模拟数组: #include <stdio.h> #include <malloc.h> int main(void) { int** ...
-
【Android进阶】关于PagerAdapter的使用方法的总结
PagerAdapter简介 PagerAdapter是android.support.v4包中的类,它的子类有FragmentPagerAdapter, FragmentStatePagerAdap ...
-
Linux系统7个运行级别(runlevel)(转)
原文地址:http://www.cnblogs.com/dkblog/archive/2011/08/30/2160191.html Linux系统有7个运行级别(runlevel) 运行级别0:系统 ...
-
mysql数据库设计三范式
为了建立冗余较小.结构合理的数据库,设计数据库时必须遵循一定的规则.在关系型数据库中这种规则就称为范式.范式是符合某一种设计要求的总结.要想设计一个结构合理的关系型数据库,必须满足一定的范式. 在实际 ...
- vue生命周期图片
-
关于Class对象、类加载机制、虚拟机运行时内存布局的全面解析和推测
简介: 本文是对Java的类加载机制,Class对象,反射原理等相关概念的理解.验证和Java虚拟机中内存布局的一些推测.本文重点讲述了如何理解Class对象以及Class对象的作用. 欢迎探讨,如有 ...
-
build.gradle 中compileSdkVersion,minSdkVersion,targetSdkVersion,buildToolsVersion的意思
compileSdkVersion: 编译版本:compileSdkVersion告诉gradle使用哪个版本AndroidSDK编译你的应用: minSdkVersion: 最低SDK版本:他代表的 ...
-
windows登陆密码破解方法之一
网上的一些人让别人进入命令提示符安全模式,我比较奇怪如果没有密码怎么进去?能进去干嘛还要进去? 本笨方法的原理主要是利用登陆界面的一些程序入口,把它当成后门来使用,比如win7登陆界面上除了输密码的地 ...
-
简单说说Spring Security 使用(附加验证码登录,自定义认证)
先看官方文档:http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/ spring security4已 ...