共计 3821 个字符,预计需要花费 10 分钟才能阅读完成。
HTTP 协定
HTTP 协定 超文本传输协定 由万维网制订(w3c)
是浏览器与服务器通信的应用层协定,规定了浏览器与服务器之间的交互规定以及交互数据的
格局信息等。
HTTP 协定对应客户端与服务端之间的交互规定有以下定义:
要求浏览器与服务端之间必须遵循一问一答的规定,即:浏览器与服务端建设 TCP 连贯后须要
先发送一个申请(问)而后服务端接管到申请并予以解决后再发送响应(答)。留神,服务端永远
不会被动给浏览器发送信息。
HTTP 要求浏览器与服务端的传输层协定必须是牢靠的传输,因而是应用 TCP 协定作为传输层
协定的。
HTTP 协定对于浏览器与服务器之间交互的数据格式,内容也有肯定的要求。
浏览器给服务端发送的内容称为申请 Request
服务端给浏览器发送的内容称为响应 Response
申请和响应中大部分内容 都是文本信息(字符串)。并且这些文本数据应用的字符集为:
ISO8859-1. 这是一个欧洲的字符集,外面是不反对中文的!!而实际上申请和响应呈现
的字符也就是英文、数字、符号。
申请 Request
申请是浏览器发送给服务端的内容,HTTP 协定中一个申请由三局部形成:
别离是:申请行,音讯头,音讯注释。音讯注释局部能够没有。
1:申请行
申请行是一行字符串,以间断的两个字符(回车符和换行符)作为完结这一行的标记。
回车符:在 ASC 编码中 2 进制内容对应的整数是 13. 回车符通常用 cr 示意。
换行符:在 ASC 编码中 2 进制内容对应的整数是 10. 换行符通常用 lf 示意。
回车符和换行符实际上都是不可见字符。
申请行分为三局部:
申请形式(SP)形象门路(SP)协定版本(CRLF)注:SP 是空格
GET /index.html HTTP/1.1
2:音讯头
音讯头是浏览器能够给服务端发送的一些附加信息,有的用来阐明浏览器本身内容,有的用来告知服务端交互细节,有的告知服务端音讯注释详情等。
音讯头由若干个组成,每行完结也是以 CRLF 标记。
每个音讯头的格局为:音讯头的名字(:SP)音讯的值(CRLF)
音讯头局部完结是以独自的(CRLF)标记。
例如:
GET /index.html HTTP/1.1
Host: localhost:8088
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
一、第一版
WebServer Web 容器,模仿 Tomcat 的根底性能
Web 容器的主要职责是
1:治理上面所有部署的 webapp(web 利用)每一个 web 利用都会蕴含本人的网页,资源,对应的业务代码(java 代码,解决逻辑的)因而一个 web 利用能够看作是一个“网站”
2:与客户端(通常就是浏览器)维持 TCP 的连贯以及基于 HTTP 协定的交互,使得浏览器能够通过网络拜访某个 web 利用的性能。
public class WebServer {
private ServerSocket server;
public WebServer(){
try{
System.out.println(“ 正在启动服务端 …”);
server = new ServerSocket(8088);
System.out.println(“ 启动服务端结束!”);
}catch(Exception e){
e.printStackTrace();
}
}
public void start(){
try {
System.out.println(“ 期待客户端连贯 …”);
Socket socket = server.accept();
System.out.println(“ 一个客户端连贯了!”);
InputStream in = socket.getInputStream();
int d=0;
while((d= in.read())!=-1){
System.out.println((char)d);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
WebServer server = new WebServer();
server.start();
}
}
二、第二版
本版本次要测试从申请中读取一行字符串的操作
一个申请中的申请行和音讯头有一个共同点,都是以 CRLF 结尾的一行字符串。因而实现了
读取一行字符串的操作后就能够复用他来实现解析申请行和音讯头的工作。
因为服务端要解决多客户端,所以依然应用线程解决客户端的交互:ClientHandler。
实现:
1:在 com.webserver.core 包下新建类:ClientHandler
2:在 WebServer 中接管客户端连贯后启动线程
3:在 ClientHandler 中实现测试读取一行字符串的操作
三、第三版
本版本进行对申请的解析工作
思路:
设计一个类:HttpRequet, 使这个类的每一个实例示意浏览器发送过去的一个具体申请内容
这个类中设计若干属性,别离示意一个申请中的各项信息。这样一来当咱们读取一个申请内容
后用一个 HttpRequest 示意后,能够通过获取该对象的属性值来获取对应的信息便于后续解决
申请的工作。
实现:
1:创立一个新的包:com.webserver.http
在这个包中保留所有和 HTTP 无关的类
2:在 http 包中创立 HttpRequest 即:申请对象
3:实现 HttpRequest 的性能
4:在 ClientHandler 中第一个环节解析申请时实例化 HttpRequest,实现解析申请。
四、第四版
实现 ClientHandler 解决申请的环节
用户在浏览器上输出地址如:
http://localhost:8008/myweb/index.html
心愿申请对应的页面,解决环节在作用就是依据用户申请的地址寻找这个文件,而后依据是否
找的做分支解决,以便后续第三步响应客户端时的操作。
实现:
1:在我的项目目录下新建一个目录 webapps,用这个目录存所有部署的网络应用。每个网络应用以
一个子目录模式保留,并且目录名就是这个利用的名字。
2:在 webapps 目录下新建第一个子目录 myweb 作为咱们第一个网络应用。
3:在 myweb 目录下新建高利用中的第一个页面:index.html
4:用户在浏览器申请如下门路:
http://localhost:8088/myweb/index.html
ClientHandler 增加第二步解决申请的工作
4.1 首先从 request 对象中获取申请的形象门路,
即:uri 属性的值。该值该当为:/myweb/index.html
4.2 依据这个值创立一个 File 从 ”./webapps” 目录下绝对该 uri 的值找到对应文件
并通过判断该文件是否存在定义好分支。
五、第五版
此版本开始实现响应客户端的工作
上一个版本中咱们曾经在 ClientHandler 中增加分支,这里先实现资源已找到的响应过程。
此时咱们该当将该资源已一个规范的 HTTP 响应格局发送给客户端使其展现该资源。
实现:
在 ClientHandler 的找到资源的分支中,通过 socket 获取输入流,发送一个响应并测试资源
存在的状况浏览器是否正确显示。
六、第六版
此版本持续开始实现响应客户端的工作
上一个版本中咱们曾经将用户申请的资源响应了,本版本咱们来实现如果资源不存在时响应
404 页面的工作。
实际上当用户申请的资源不存在,那么服务端发送的响应中状态代码为 404,用来告知浏览器
申请的门路有效。并能够同时响应一个 404 页面进行展现。
实现:
1:在 webaaps 目录下新建一个目录 root
2:在 root 目录下新建页面:404.html
转让给页面中只须要居中显示一行字:404!资源不存在!
注:该页面没有放在 myweb 目录下,而是放在 root 目录下的起因是无论用户未来申请哪个
网络应用下的资源都可能存在着资源没有找到的状况,因而响应 404 这个页面是一个
通用操作,所有未来把所有通用的页面放在 root 下共用即可。
3:在 ClientHandler 解决申请环节中资源不存在的分支里,响应 404.
状态行内容为;HTTP/1.1 404 NOT FOUND
响应头不变,还是 Content-type 与 Content-Length,留神,长度该当是 404 页面的长度
响应注释则是将 404 页面的内容发送到客户端。
启动程序后做如下测试:
http://localhost:8088/myweb/indes.html 注:index1.html 在 myweb 目录下没有
此时该当能看到 404 页面显示在浏览器中