1. 客户端,浏览器
2. 服务端基于 socket的 协议解析
1. 服务端接收GET请求
运行服务端代码 HttpServerGet,浏览器客户端 请求路径:http://localhost:8888/ GET请求直接放入浏览器地址栏即可
package com.denganzhi.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServerGet {
public static void main(String[] args) {
//1.. 创建服务器, 指定端口
ServerSocket server;
try {
server = new ServerSocket(8888);
// 2. 指定客户端 阻塞式
// 完成 三次握手 , 建立管道
System.out.println("服务器阻塞,等待客户端连接");
Socket socket= server.accept();
System.out.println("一个客户端建立连接");
String msg=null;
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuffer sb=new StringBuffer();
while((msg=br.readLine()).length() > 0) {
sb.append(msg);
sb.append("\n");
if(msg==null) {
break;
}
}
String reqStr= sb.toString();
System.out.println("reqStr:"+reqStr);
// 请求路径:http://localhost:8888/ GET请求直接放入浏览器地址栏即可
// 输出内容
//reqStr:GET / HTTP/1.1 //GET请求行
//Host: localhost:8888 // GET请求头,GET没有请求体
//Connection: keep-alive
//Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
//Upgrade-Insecure-Requests: 1
//User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
//Accept-Encoding: gzip, deflate, sdch
//Accept-Language: zh-CN,zh;q=0.8
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.服务端接收POST请求
客户端代码index.html: 发送
http://localhost:8888/ POST 请求
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form method="post" action="http://localhost:8888/">
用户名:<input type="text" name="username" />
密码:<input type="text" name="pwd" />
<input type="submit" value="登录" />
</form>
</body>
</html>
服务端解析POST请求HttpServerPost,拼接响应POST请求
获取post请求内容:
post请求结果是:POST / HTTP/1.1
Host: localhost:7676
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
Connection: keep-alive
Upgrade-Insecure-Requests: 1
username=eee&pwd=
post请求响应内容:
响应行:
HTTP/1.1 404 NOTFOUNDPAGER
响应头
Server:xiaozhi Server/0.0.1
Date:Mon Apr 06 21:37:10 CST 2020
Content-type:text/html;charset=GBK
Content-Length:0
响应体:
HTML代码
package com.denganzhi.socket;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class HttpServerPost {
// 请求路径:http://localhost:9999/
public static void main(String[] args) {
//1.. 创建服务器, 指定端口
ServerSocket server;
try {
server = new ServerSocket(9999);
// 2. 指定客户端 阻塞式
// 完成 三次握手 , 建立管道
System.out.println("服务器阻塞,等待客户端连接");
Socket client= server.accept();
System.out.println("一个客户端建立连接");
byte[] data=new byte[20480];
// 接收客户端请求POST
int len=client.getInputStream().read(data);
String requestInfo=new String(data,0,len);
// post请求结果是:POST / HTTP/1.1 请求行
// Host: localhost:9999 请求头
// Connection: keep-alive
// Content-Length: 20
// Cache-Control: max-age=0
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
// Origin: http://127.0.0.1:8020
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
// Content-Type: application/x-www-form-urlencoded
// Referer: http://127.0.0.1:8020/HelloHBuilder/index2.html?__hbt=1586174211226
// Accept-Encoding: gzip, deflate
// Accept-Language: zh-CN,zh;q=0.8
//
// username=111&pwd=111 请求体,请求体和请求头中间有换行
System.out.println("post请求结果是:"+requestInfo);
/***
*
* 响应行:HTTP/1.1 200 OK
* 响应头:
* Server:xiaozhi Server/0.0.1
Date:Mon Apr 06 20:34:05 CST 2020
Content-type:text/html;charset=GBK
Content-Length:144
响应头: 可以是text/html : 网页内容
可以是json
可会是文件 流
可以是图片
*
*/
String CRLF="\r\n";
String BLANK=" ";
// 响应
StringBuilder responseContext=new StringBuilder();
responseContext.append("<!DOCTYPE html>\r\n" +
"<html>\r\n" +
" <head>\r\n" +
" <meta charset=\"UTF-8\">\r\n" +
" <title>小置同学</title>\r\n" +
" </head>\r\n" +
" <body>\r\n" +
" hello!小置同学\r\n" +
" </body>\r\n" +
"</html>\r\n" +
"");
System.out.println("响应体:"+responseContext);
StringBuilder response =new StringBuilder();
//1) HTTP协议版本、状态代码、描述
response.append("HTTP/1.1").append(BLANK).append("200").
append(BLANK).append("OK").append(CRLF);
System.out.println("响应行:"+response.toString());
//2) 响应头(Response Head)
response.append("Server:xiaozhi Server/0.0.1").append(CRLF);
response.append("Date:").append(new Date()).append(CRLF);
response.append("Content-type:text/html;charset=GBK").
append(CRLF);
//正文长度 :字节长度
response.append("Content-Length:").
// 正文长度,这里必须是字节数正文的
append(responseContext.toString().getBytes().length).
append(CRLF);
//3)正文之前
response.append(CRLF);
//4)正文
response.append(responseContext);
System.out.println("响应头:"+response);
//输出流
BufferedWriter bw = new BufferedWriter(new
OutputStreamWriter(client.getOutputStream()));
bw.write(response.toString());
bw.flush();
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.获取状态码、请求参数解析, 实现tomcat功能 HttpServerPostAddStatus
package com.denganzhi.socket;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class HttpServerPostAddStatus {
// 请求路径:http://localhost:7676/
public static void main(String[] args) {
//1.. 创建服务器, 指定端口
ServerSocket server;
try {
server = new ServerSocket(7676);
// 2. 指定客户端 阻塞式
// 完成 三次握手 , 建立管道
System.out.println("HttpServerPostAddStatus->服务器阻塞,等待客户端连接");
Socket client= server.accept();
System.out.println("一个客户端建立连接");
byte[] data=new byte[20480];
// 接收客户端请求POST
int len=client.getInputStream().read(data);
String requestInfo=new String(data,0,len);
// post请求结果是:POST / HTTP/1.1 请求行
// Host: localhost:9999 请求头
// Connection: keep-alive
// Content-Length: 20
// Cache-Control: max-age=0
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
// Origin: http://127.0.0.1:8020
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
// Content-Type: application/x-www-form-urlencoded
// Referer: http://127.0.0.1:8020/HelloHBuilder/index2.html?__hbt=1586174211226
// Accept-Encoding: gzip, deflate
// Accept-Language: zh-CN,zh;q=0.8
//
// username=111&pwd=111 请求体,请求体和请求头中间有换行
System.out.println("post请求结果是:"+requestInfo);
/***
*
* 响应行:HTTP/1.1 200 OK
* 响应头:
* Server:xiaozhi Server/0.0.1
Date:Mon Apr 06 20:34:05 CST 2020
Content-type:text/html;charset=GBK
Content-Length:144
响应头: 可以是text/html : 网页内容
可以是json
可会是文件 流
可以是图片
*
*/
String CRLF="\r\n";
String BLANK=" ";
// 响应
StringBuilder responseContext=new StringBuilder();
// responseContext.append("<!DOCTYPE html>\r\n" +
// "<html>\r\n" +
// " <head>\r\n" +
// " <meta charset=\"UTF-8\">\r\n" +
// " <title>小置同学</title>\r\n" +
// " </head>\r\n" +
// " <body>\r\n" +
// " hello!小置同学\r\n" +
// " </body>\r\n" +
// "</html>\r\n" +
// "");
System.out.println("响应体:"+responseContext);
StringBuilder response =new StringBuilder();
//1) HTTP协议版本、状态代码、描述
// 状态码描述
int statusCode=404;
response.append("HTTP/1.1").append(BLANK).append(statusCode);
switch (statusCode) {
case 200:
response.append(BLANK).append("OK").append(CRLF);
break;
case 404:
response.append(BLANK).append("NOTFOUNDPAGER").append(CRLF);
break;
case 500:
response.append(BLANK).append("ServerError").append(CRLF);
break;
}
System.out.println("响应行:"+response.toString());
//2) 响应头(Response Head)
response.append("Server:xiaozhi Server/0.0.1").append(CRLF);
response.append("Date:").append(new Date()).append(CRLF);
response.append("Content-type:text/html;charset=GBK").
append(CRLF);
//正文长度 :字节长度
response.append("Content-Length:").
// 正文长度,这里必须是字节数正文的
append(responseContext.toString().getBytes().length).
append(CRLF);
//3)正文之前
response.append(CRLF);
//4)正文
response.append(responseContext);
System.out.println("响应头:"+response);
//输出流
BufferedWriter bw = new BufferedWriter(new
OutputStreamWriter(client.getOutputStream()));
bw.write(response.toString());
bw.flush();
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
火狐浏览器 抓包查看 请求、响应状态码: