请求协议
概念:Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输规则。
特点:
1、基于TCP协议,面向连接,安全
2、基于请求-响应模型:一次请求对应一次响应
3、HTTP协议是无状态协议:对于事务处理没有记忆能力,每次请求-响应都是独立的
优点:速度快
缺点:多次请求间不能共享数据
HTTP请求数据格式:
请求行:请求数据第一行(请求方式、资源路径、协议和版本号)
请求头:第二行开始,key:value格式
请求体:post方式最后一行,和请求头有一行间隔,存放请求参数
下面是浏览器开发者工具截图
再带大家回顾一下post请求和get请求(这也是一道面试题哦!):
post:请求参数放在请求体中,没有大小限制
get:请求参数在请求行中,有大小限制
响应协议
HTTP响应数据格式:
响应行:响应数据第一行(协议和版本号、状态码、描述)
响应头:第二行开始,key:value格式
响应体:存放响应数据
常见状态码:
其中200、404、500是最重要的状态码,要知道他们的含义
常见响应头(可以不用记见多了就知道是什么意思了 ):
协议解析代码
package com.itheima;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/*
* 自定义web服务器
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8080); // 监听指定端口
System.out.println("server is running...");
while (true){
Socket sock = ss.accept();
System.out.println("connected from " + sock.getRemoteSocketAddress());
//开启线程处理请求
Thread t = new Handler(sock);
t.start();
}
}
}
class Handler extends Thread {
Socket sock;
public Handler(Socket sock) {
this.sock = sock;
}
public void run() {
try (InputStream input = this.sock.getInputStream(); OutputStream output = this.sock.getOutputStream()) {
handle(input, output);
} catch (Exception e) {
try {
this.sock.close();
} catch (IOException ioe) {
}
System.out.println("client disconnected.");
}
}
private void handle(InputStream input, OutputStream output) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
// 读取HTTP请求:
boolean requestOk = false;
String first = reader.readLine();
if (first.startsWith("GET / HTTP/1.")) {
requestOk = true;
}
for (;;) {
String header = reader.readLine();
if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕
break;
}
System.out.println(header);
}
System.out.println(requestOk ? "Response OK" : "Response Error");
if (!requestOk) {// 发送错误响应:
writer.write("HTTP/1.0 404 Not Found\r\n");
writer.write("Content-Length: 0\r\n");
writer.write("\r\n");
writer.flush();
} else { // 发送成功响应:
//读取html文件,转换为字符串
InputStream is = Server.class.getClassLoader().getResourceAsStream("html/a.html");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder data = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null){
data.append(line);
}
br.close();
int length = data.toString().getBytes(StandardCharsets.UTF_8).length;
writer.write("HTTP/1.1 200 OK\r\n");
writer.write("Connection: keep-alive\r\n");
writer.write("Content-Type: text/html\r\n");
writer.write("Content-Length: " + length + "\r\n");
writer.write("\r\n"); // 空行标识Header和Body的分隔
writer.write(data.toString());
writer.flush();
}
}
}