Web入门-06.HTTP协议-协议解析

浏览器发起HTTP协议请求,服务端通过ServerSocket接收并交给一个Socket对象(管道),然后解析浏览器的请求,并通过Socket管道向浏览器响应。

代码如下:

java 复制代码
package com.gjw;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("server is running...");

        while (true) {
            Socket socket = serverSocket.accept();
            System.out.println("connected form" + socket.getRemoteSocketAddress());


            new Handler(socket).start();
        }
    }
}

class Handler extends Thread {
    private Socket socket;
    public Handler(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {

        try (
                // 字节输入流:读入客户端发起的GET请求    字节输出流:写出服务端提供的服务
                InputStream is = socket.getInputStream();
                OutputStream os = socket.getOutputStream()
                )
        {
            handle(is, os);
        } catch (Exception e) {
            try {
                socket.close();
            } catch (IOException ex) {
                System.out.println("client disconnected");
            }
        }
    }

    private void handle(InputStream is, OutputStream os) throws Exception {
        // reader:读取客户端发来的GET请求
        BufferedReader reader = new BufferedReader(new InputStreamReader(is,StandardCharsets.UTF_8));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os,StandardCharsets.UTF_8));

        boolean requestOk = false;

        String first = reader.readLine();
        if (first.startsWith("GET / HTTP/1.")) {
            requestOk = true;
        }

        String header;
        while (!(header = reader.readLine()).isEmpty()) {    // 使用isEmpty判断,这样可以值判断到请求头就结束。因为请求头和请求体之间有空行
            System.out.println(header);
        }

/*        String line;
        while ((line = reader.readLine()) != null){
        不能使用 != null,因为HTTP请求中,请求头和请求体中是一个空行,使用请求!= null判断会使得无法将请求头和请求体分开,导致一直读到
        该http请求的末尾,这样的的话可能会导致该循环一直进行,因为客户端可能会不断发送HTTP请求,导致服务器无限等待输入特别是在客户端保持连接
        (例如HTTP/1.1中的Connection: keep-alive头部时)。这样,服务器可能不会及时处理和发送响应,从而导致后面的代码无法运行。
            System.out.println(line);
        }*/

        System.out.println(requestOk ? "Response OK" : "Response Error");

        if (requestOk) {
            InputStream input = Server.class.getClassLoader().getResourceAsStream("html/a.html");
            BufferedReader br = new BufferedReader(new InputStreamReader(input));
            StringBuffer sb = new StringBuffer();

            String content;
            while ((content = br.readLine()) != null) {
                sb.append(content);
            }


            br.close();
            int length = sb.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(sb.toString());
            writer.flush();
        } else {
            writer.write("HTTP/1.0 404 Not Found\r\n");
            writer.write("Content-Length: 0\r\n");
            writer.write("\r\n");
            writer.flush();
        }
    }
}

响应的是一个表格数据

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        table {
            margin: 0 auto;
            text-align: center;
            border: 1px solid black;
            border-collapse: collapse;
            width: 500px;
        }
        th,td {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <table>
        <tr>
            <th>序号</th>
            <th>品牌名称</th>
            <th>企业名称</th>
        </tr>
        <tr>
            <td>010</td>
            <td>三只松鼠</td>
            <td>三只松鼠</td>
        </tr>
        <tr>
            <td>009</td>
            <td>优衣库</td>
            <td>优衣库</td>
        </tr>
        <tr>
            <td>008</td>
            <td>小米</td>
            <td>小米科技有限公司</td>
        </tr>
    </table>
</body>
</html>

可以看到这样的过程很繁琐,这还仅仅是针对一个demo程序,如果要手动编写程序去解析http协议,那就太麻烦了。但所有的web项目开发都需要解析http协议,但是http协议是标准的,是统一固定的,因此代码是通用的。所以很多已经将代码写好封装在app中供我们使用,而这个app就是web服务器,比如Tomcat。这样就不用去管解析http协议了,而只需要关注业务逻辑的开发了。

相关推荐
せいしゅん青春之我23 分钟前
【JavaEE初阶】IP协议-IP地址不够用了咋办?
java·服务器·网络·网络协议·tcp/ip·java-ee
我最厉害。,。38 分钟前
内网对抗-隧道技术篇&防火墙组策略&HTTP反向&SSH转发&出网穿透&CrossC2&解决方案
网络协议·http·ssh
汤愈韬40 分钟前
网络通信原理
网络·网络安全
门思科技1 小时前
LoRaWAN通信协议详解:架构、加密机制与核心应用
运维·服务器·网络·嵌入式硬件·物联网
程思扬1 小时前
开源 + 实时 + 无网络限制:Excalidraw 是流程图协作新选择
网络·人工智能·阿里云·ai·开源·流程图
测绘小沫-北京云升智维1 小时前
徕卡RTC360三维激光扫描仪摔坏故障维修方案
网络
视觉震撼2 小时前
RDP登录事件详细溯源分析脚本(兼容Windows PowerShell版本)
运维·网络·windows·网络安全·网络攻击模型·安全威胁分析·安全架构
Pluchon2 小时前
硅基计划6.0 陆 JavaEE Http&Https协议
网络协议·tcp/ip·http·网络安全·https·udp·java-ee
2501_915909062 小时前
深入理解HTTPS和HTTP的区别、工作原理及安全重要性
安全·http·ios·小程序·https·uni-app·iphone
是店小二呀2 小时前
仓颉三方库开发实战:Simple HTTP Server 实现详解
网络·网络协议·http