手写一个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 ...
随机推荐
- selenium常用操作学习笔记
一,弹窗处理(推荐文章:https://blog.csdn.net/huilan_same/article/details/52298460) selenium提供switch_to方法定位弹窗的对话 ...
- C语言入门编程需要掌握的核心要点有哪些? 为你总结了这20个!
摘要: C语言作为编程的入门语言,学习者如何快速掌握其核心知识点,面对茫茫书海,似乎有点迷茫.为了让各位快速地掌握C语言的知识内容,在这里对相关的知识点进行了归纳. 引言 C语言精简的语法集和标准库, ...
- 【C语言/C++编程学习笔记】:通俗易懂讲解 - 链表!学不会?不存在的!
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- 面试官:如何写出让 CPU 跑得更快的代码?
前言 代码都是由 CPU 跑起来的,我们代码写的好与坏就决定了 CPU 的执行效率,特别是在编写计算密集型的程序,更要注重 CPU 的执行效率,否则将会大大影响系统性能. CPU 内部嵌入了 CPU ...
- swoft运行流程
启动命令 php bin/swoft http:start 或者 swoftctl run -c http:start 1 入口文件 bin/swoft.php #!/usr/bin/env php ...
- git永久保存账号密码,免去git重复输入账号密码操作
这是我刚刚遇到的问题,每次操git操作都要输入用户名和密码,网上百度了下搜到了方法解决了 方法一:(快捷简单) 直接在git bash 中执行命令:git config --global creden ...
- zookeeper核心之ZAB协议就这么简单!
背景 我们都知道 Zookeeper 是基于 ZAB 协议实现的,在介绍 ZAB 协议之前,先回顾一下 Zookeeper 的起源与发展. Zookeeper 究竟是在什么样的时代背景下被提出?为了解 ...
- JS错误写法[清除DOM]
前言 我现在总结一下我之前敲代码犯的错误,清除DOM元素,我们开始写代码吧! HTML <h1 style="font-size: 18px;font-weight: bold;col ...
- 【Azure微服务 Service Fabric 】因证书过期导致Service Fabric集群挂掉(升级无法完成,节点不可用)
问题描述 创建Service Fabric时,证书在整个集群中是非常重要的部分,有着用户身份验证,节点之间通信,SF升级时的身份及授权认证等功能.如果证书过期则会导致节点受到影响集群无法正常工作. 当 ...
- vscode按下F5黑窗口显示的是乱码
找了很多方法,powershell修改了也变不了 最后找到了这个链接的方法:https://blog.csdn.net/weixin_40040107/article/details/10372155 ...