手写一个Web服务器,极简版Tomcat
网络传输是通过遵守HTTP协议的数据格式来传输的。
HTTP协议是由标准化组织W3C(World Wide Web Consortium,万维网联盟)和IETF(Internet Engineering Task Force,国际互联网工程任务组)推动和制定的,最后形成RFC文档 [RFC1945](HTTP/1.0)和RFC2616[HTTP/1.1]
可以响应HTTP请求的程序就是Web Server,实现方法并没有统一规范,可以说HTTP协议就是Web Server和网络传输数据之间的接口规范。以后我们会看到,Web Server和处理程序之间的规范是CGI。
一些常见的Web Server有Apache、Nginx、Microsoft IIS、Google GWS。
我们这里手写一个Web Server。
首先我们需要接收网络的请求,根据OSI七层模型,网络的实现是分层的。Web Server属于应用层,要调用下一层(传输层,TCP/IP)的接口,来得到对方发来的网络请求,这个接口就叫做Socket。《计算机网络:自顶向下方法》中写到:“Socket是同一台主机内应用层与传输层之间的接口。因为Socket是建立网络应用程序的可编程接口,所以Socket也被称为应用程序和网络之间的API”。
一、最简单的Web Server
要编写一个Web Server,我们调用系统Socket接口,监听8180端口上收到的网络数据,打印到控制台,并给出一个符合http标准的响应,代码如下:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Server {
public static void main(String[] args) {
Server server = new Server();
server.start();
}
public void start() {
try {
ServerSocket serverSocket = new ServerSocket(8180); // 调用系统socket接口,监听某端口的socket请求
Socket httpInputSocket = serverSocket.accept(); // 在这里,程序线程等待socket输入
this.printHttpRequest(httpInputSocket);
this.responseHttpRequest(httpInputSocket);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 打印来自外部的http请求
*
* @param httpInputSocket
*/
private void printHttpRequest(Socket httpInputSocket) {
try {
// 调用系统IO,打印请求
BufferedReader br = new BufferedReader(new InputStreamReader(httpInputSocket.getInputStream()));
StringBuilder receivedHttp = new StringBuilder();
String line = null;
while ( !"".equals(line = br.readLine())) {
receivedHttp.append(line);
receivedHttp.append(System.getProperty("line.searator", "\n"));
}
System.out.println(receivedHttp.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 返回页面供请求方显示
*
* @param httpInputSocket
*/
private void responseHttpRequest(Socket httpInputSocket) {
// 创建响应体
StringBuilder contextText = new StringBuilder();
contextText.append(
"<html>" +
"<head>" +
"<title>Build A Web Server</title>" +
"</head>" +
"<body>Hello World, This is my page</body>" +
"</html>");
// 创建响应头
StringBuilder headText = new StringBuilder();
headText.append("HTTP/1.1").append(" ").append("200").append(" ").append("OK").append("\n");
headText.append("Server:myServer").append(" ").append("0.0.1v").append(" ");
headText.append("Date:Sat,"+" ").append(new Date()).append("\n");
headText.append("Content-Type:text/html;charset=UTF-8").append("\n");
headText.append("Content-Length:").append(contextText.toString().getBytes().length).append("\n");
// http response
StringBuilder responseText = new StringBuilder();
responseText.append(headText).append("\n").append(contextText);
System.out.println(responseText);
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(httpInputSocket.getOutputStream()));
bw.write(responseText.toString());
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
至此,一个100行不到的Web Server就写好了,运行一下,在浏览器里访问:http://localhost:8180/,可以看到结果:
程序控制台也正确打印:
这个Web Server会对请求到8180端口的所有请求都返回同样的页面,比如我们访问http://localhost:8180/really?foo=123,结果也是一样的:
从这个例子可以看出,通过HTTP请求进行访问,可以不用创建socket客户端。
注意printHttpRequest和responseHttpRequest都要调用才能显示效果,就是说先执行socket 输入流的读取,然后再执行socket输出流输出
手写一个Web服务器,极简版Tomcat的更多相关文章
- Tomcat源码分析 (一)----- 手写一个web服务器
作为后端开发人员,在实际的工作中我们会非常高频地使用到web服务器.而tomcat作为web服务器领域中举足轻重的一个web框架,又是不能不学习和了解的. tomcat其实是一个web框架,那么其内部 ...
- 用C写一个web服务器(二) I/O多路复用之epoll
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
- 使用node.js 文档里的方法写一个web服务器
刚刚看了node.js文档里的一个小例子,就是用 node.js 写一个web服务器的小例子 上代码 (*^▽^*) //helloworld.js// 使用node.js写一个服务器 const h ...
- 使用Node.js原生API写一个web服务器
Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点.一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa.但 ...
- wsgiref手写一个web服务端
''' 通过wsgiref写一个web服务端先讲讲wsgiref吧,基于网络通信其根本就是基于socket,所以wsgiref同样也是通过对socket进行封装,避免写过多的代码,将一系列的操作封装成 ...
- 用java写一个web服务器
一.超文本传输协议 Web服务器和浏览器通过HTTP协议在Internet上发送和接收消息.HTTP协议是一种请求-应答式的协议——客户端发送一个请求,服务器返回该请求的应答.HTTP协议使用可靠的T ...
- 【教程】手写简易web服务器
package com.littlepage.testjdbc; import java.io.BufferedReader; import java.io.FileReader; import ja ...
- 手写简易WEB服务器
今天我们来写一个类似于Tomcat的简易服务器.可供大家深入理解一下tomcat的工作原理,本文仅供新手参考,请各位大神指正!首先我们要准备的知识是: Socket编程 HTML HTTP协议 服务器 ...
- 用C写一个web服务器(一) 基础功能
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
随机推荐
- Python中列表、元组、字典、集合与字符串,相关函数,持续更新中……
本篇博客为博主第一次学 Python 所做的笔记(希望读者能够少点浮躁,认真阅读,平心静气学习!) 补充: 列表.元组和字符串共同属性: 属于有序序列,其中的元素有严格的先后顺序 都支持双向索引,索引 ...
- <bdi> 标签
bdi 指的是 bidi 隔离. <bdi> 标签允许您设置一段文本,使其脱离其父元素的文本方向设置. 在发布用户评论或其他您无法完全控制的内容时,该标签很有用. 实例 把用户名从周围的文 ...
- Linux显示系统信息sh脚本
#!/bin/bash # #******************************************************************** #Author: wangxia ...
- Linux中创建自己的欢迎登陆界面
/etc 在Linux中相当于Windows的注册表 修改其中文件可以影响整个Linux系统 MOTD motd:message of the day /etc/motd /etc/motd文件作用是 ...
- APP打开(二)—标准流程
APP打开是一个老生常谈的话题,在互联网时代,在APP遍地的时代,APP打开是每一个APP的必经之路,今天我想通过以下几点来阐述APP打开的标准流程,给这个话题写一点自己的见解. APP打开现状 标准 ...
- python第二章:控制流
变成实际上是一个过程的提现,每个过程都是有多个流程块组成. 比如:判断是否下雨的过程 1.布尔值 在第一章最后举例了比较操作后,最终返回的结果 True or False True 和 False是一 ...
- Spring 事务失效
隔离级别 在 TransactionDefinition.java 接口中,定义了"四种"的隔离级别枚举: /** * [Spring 独有]使用后端数据库默认的隔离级别 * * ...
- list.add方法参数详解
- Python&&Pip
Pip简易使用 使用pip list命令就可以发现自己电脑里所安装库的名字.如图展示的出来的有package.Version.Location三列,package是下载的python库名,Versio ...
- 【转】Setting up SDL Extension Libraries on MinGW
FROM:http://lazyfoo.net/tutorials/SDL/06_extension_libraries_and_loading_other_image_formats/windows ...