• How Tomcat Works 第一章 - 了解HTTP、Socket、ServerSocket构建简单的 Web 服务器



    文章简介

    本章主要是对How Tomcat Works第一章内容进行归纳,了解一个简单的HTTP服务器是如何运行,以及尝试搭建一个简单的服务器,所需要java.net里面的SocketServerSocket类的基本运用。在了解SocketServerSocket之后,手动简单搭建一个最基础的HTTP服务器。


    一、了解超文本传输协议 - HTTP

    HTTP 是一种传输协议,全称HyperText Transfer Protocol,我们通常称为超文本传输协议。HTTP允许 web 服务器和浏览器通过互联网进行来发送和接受数据。它是一种请求和响应协议。客户端请求一个文件而服务器响应请求。HTTP 使用可靠的 TCP 连接,TCP 默认
    使用 80 端口。第一个 HTTP 版是 HTTP/0.9,然后被 HTTP/1.0 所替代。而现在我们常用的协议版本已升至HTTP/1.1
    HTTP 中,始终都是客户端通过建立连接和发送一个 HTTP 请求从而开启一个事务。web 服务器不需要联系客户端或者对客户端做一个回调连接。无论是客户端或者服务器都可以提前终止连接。举例来说,当你正在使用一个 web 浏览器的时候,可以通过点击浏览器上的停止按钮来停止一个文件的下载进程,从而有效的关闭与 web 服务器的 HTTP 连接。

    1.1、HTTP 请求

    一个标准的HTTP请求应该包含以下三个部分:

    (1)请求方法—统一资源标识符(URI)—请求协议/版本
    (2)请求头
    (3)请求内容

    这里我为大家提供了一个HTTP请求的例子:

    GET /index HTTP/1.1
    Host: localhost:8080
    Connection: keep-alive
    sec-ch-ua: "Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"
    sec-ch-ua-mobile: ?0
    sec-ch-ua-platform: "Windows"
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
    Sec-Fetch-Site: none
    Sec-Fetch-Mode: navigate
    Sec-Fetch-User: ?1
    Sec-Fetch-Dest: document
    Accept-Encoding: gzip, deflate, br, zstd
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: Idea-2110620b=1a0ceb21-c419-46ec-9d3e-3a72f70217f0; token=dc565de2-f7e5-41b0-b22d-447c340a5a86
    
    name=TOMCAT&age=18
    

    请求方法—统一资源标识符(URI)—请求协议/版本对应第一行: GET /index HTTP/1.1

    这里GET是请求方法,/indexURI,而 HTTP/1.1 是协议/版本。HTTP1.1一共支持7种类型的请求,分别是:GET、POST、HEAD、OPTIONS、PUT、DELETE、TRACE。当然互联网中最常用的就是GETPOST方法。

    请求头对应以下这一段:

    Host: localhost:8080
    Connection: keep-alive
    sec-ch-ua: "Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"
    sec-ch-ua-mobile: ?0
    sec-ch-ua-platform: "Windows"
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
    Sec-Fetch-Site: none
    Sec-Fetch-Mode: navigate
    Sec-Fetch-User: ?1
    Sec-Fetch-Dest: document
    Accept-Encoding: gzip, deflate, br, zstd
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: Idea-2110620b=1a0ceb21-c419-46ec-9d3e-3a72f70217f0; token=dc565de2-f7e5-41b0-b22d-447c340a5a86
    

    请求的头部包含了关于客户端环境和请求的主体内容的有用信息。例如它可能包括浏览器设
    置的语言,主体内容的长度等等。每个头部通过一个回车换行符(CRLF)来分隔的。
    对于 HTTP 请求格式来说,头部和主体内容之间有一个回车换行符(CRLF)是相当重要的。CRLF
    告诉HTTP服务器主体内容是在什么地方开始的。

    第三部分请求内容则对应: name=TOMCAT&age=18


    1.2、HTTP 响应

    类似于 HTTP 请求,一个 HTTP 响应也包括三个组成部分:
    (1)请求方法—统一资源标识符(URI)—请求协议/版本
    (2)响应的头部
    (3)主体内容

    下面是一个 HTTP 响应的例子:

    HTTP/1.1 200 OK
    Server: Microsoft-IIS/4.0
    Date: Mon, 5 Jan 2004 13:13:33 GMT
    Content-Type: text/html
    Last-Modified: Mon, 5 Jan 2004 13:13:12 GMT
    Content-Length: 112
    
    
    
    HTTP Response Example<<span class="token operator">/</span>title>
    <<span class="token operator">/</span>head>
    <body>
    Welcome to Brainy Software
    <<span class="token operator">/</span>body>
    <<span class="token operator">/</span>html>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code></pre> 
    <p>响应头部的第一行类似于请求头部的第一行。第一行告诉你该协议使用 <strong>HTTP</strong> 1.1,请求成功(200=成功),表示一切都运行良好,响应头部和请求头部类似,也包括很多有用的信息。响应的主体内容是响应本身的 HTML 内容。头部和主体内容通过 CRLF 分隔开来。</p> 
    <hr> 
    <h2><a name="t5"></a><a id="Socket__106"></a>二、Socket 基本概念</h2> 
    <p>套接字作为网络接入的一个端点,允许一个应用可以从网络中读取数据或者是写入数据,两个不同的计算机上的应用软件可以通过套接字进行通信,接收或者发送数据给对方。如果你想将一条信息从你的应用软件发送到另一台计算机上的应用,因此你应该知道另一个应用的IP地址和套接字端口。然后在JAVA程序语言中,套接字则是指的是java.net.Socket类。</p> 
    <h3><a name="t6"></a><a id="21_108"></a>2.1、创建一个套接字</h3> 
    <p>创建一个套接字<code>Socket对象</code>,你可以使用<code>Socket</code>类中众多构造方法中的一个:<br> <img src="https://1000bd.com/contentImg/2024/09/08/c85b55934eeab8c1.png" alt="在这里插入图片描述"></p> 
    <p><strong>public Socket(String host, int port)</strong> 构造方法算是最常用的一个构造方法。这里的参数<strong>host</strong>主机指的是远程机器名称或者机器的IP地址,<strong>port</strong>端口指的是远程应用的端口号。比如你想要创建一个连接百度的套接字,可以这样写:<code>Socket socket = new Socket("www.baidu.com", 80);</code>,一旦你成功创建一个<code>Socket</code>实例,你就可以用它来发送或者是接受字符流。要发送字节流,你首先要调用<strong>Socket</strong>实例的<strong>getOutputStream</strong>方法来获取一个<code>java.io.OutputStream</code>对象。要 发 送信息到 一 个 远 程 应 用 , 你 经 常 要 从 返 回 的 <strong>OutputStream</strong> 对 象 中 构 造 一 个<code>java.io.PrintWriter</code> 对象。要从连接的另一端接受字节流,你可以调用 <strong>Socket</strong> 类的<strong>getInputStream</strong> 方法用来返回一个 <code>java.io.InputStream</code> 对象。<br> 以下的代码片段创建了一个套接字,可以和本地 HTTP 服务器(127.0.0.1 是指本地主机)进行通讯,发送一个 HTTP 请求,并从服务器接受响应。它创建了一个 StringBuffer 对象来保存响<br> 应并在控制台上打印出来。</p> 
    <pre data-index="3" class="set-code-hide prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token operator">*</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>net<span class="token punctuation">.</span></span><span class="token class-name">Socket</span></span><span class="token punctuation">;</span>
    
    <span class="token comment">/**
     * @Author: Greyfus
     * @Create: 2024-08-02 21:45
     * @Version:
     * @Description:
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SocketDemo</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span><span class="token punctuation">,</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{<!-- --></span>
            <span class="token class-name">Socket</span> socket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Socket</span><span class="token punctuation">(</span><span class="token string">"localhost"</span><span class="token punctuation">,</span> <span class="token number">8088</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">OutputStream</span> os <span class="token operator">=</span> socket<span class="token punctuation">.</span><span class="token function">getOutputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">PrintWriter</span> out <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PrintWriter</span><span class="token punctuation">(</span>os<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"GET /hl-template/authority/verifyCode HTTP/1.1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Host: localhost:8080"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Connection: Close"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"X-TENANT_ID: HL_TEMPLATE"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"lang: en_US"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
            <span class="token class-name">BufferedReader</span> in <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">BufferedReader</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">InputStreamReader</span><span class="token punctuation">(</span>socket<span class="token punctuation">.</span><span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">StringBuffer</span> sb <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">boolean</span> loop <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            <span class="token keyword">while</span> <span class="token punctuation">(</span>loop<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>in<span class="token punctuation">.</span><span class="token function">ready</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                    <span class="token keyword">int</span> read <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
                    <span class="token keyword">while</span> <span class="token punctuation">(</span>read <span class="token operator">!=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                        read <span class="token operator">=</span> in<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        sb<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">)</span> read<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
                    loop <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
                <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"==========响应结果========"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>sb<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code></pre> 
    <p><code>请注意,为了从 web 服务器获取适当的响应,你需要发送一个遵守 HTTP 协议的 HTTP 请求。 假如你已经阅读了前面一节超文本传输协议(HTTP),你应该能够理解上面代码提到的 HTTP 请求。</code><br> 本地端口<strong>8088</strong>我已经启动了一个<strong>tomcat</strong>服务器,请求地址<code>/hl-template/authority/verifyCode</code> 是用于获取验证码接口。我们分别使用<strong>PostMan</strong>请求工具和<strong>Socket</strong>请求该接口,得到的结果是一致的。<code>要明白JAVA通信都是基于Socket的,不管是RestTemplate还是httpTemplate底层都是基于Socket来通信</code></p> 
    <p><img src="https://1000bd.com/contentImg/2024/09/08/55cd4346b6a59449.png" alt="在这里插入图片描述"><br> <img src="https://1000bd.com/contentImg/2024/09/08/a1f464b9f5f0acb6.png" alt="在这里插入图片描述"></p> 
    <hr> 
    <h2><a name="t7"></a><a id="ServerSocket__167"></a>二、ServerSocket 基本概念</h2> 
    <p><strong>Socket</strong> 类代表一个客户端套接字,即任何时候你想连接到一个远程服务器应用的时候你构造的套接字。现在,假如你想实施一个服务器应用,例如一个 <strong>HTTP</strong> 服务器或者 <strong>FTP</strong> 服务器,你需要另一种不同的做法。这是因为你的服务器必须随时待命,因为它不知道一个客户端应用什么时候会尝试去连接它。为了让你的应用能随时待命,你需要使用<code> java.net.ServerSocket</code> 类。这是服务器套接字的实现。<strong>ServerSocket</strong>和 <strong>Socket</strong> 不同在于,服务器套接字<strong>ServerSocket</strong>的角色是等待来自客户端的连接请求。一旦服务器套接字获得一个连接请求,它将创建一个 <strong>Socket</strong> 实例来与客户端进行通信。<br> 要创建一个服务器套接字,你需要使用 <strong>ServerSocket</strong> 类提供的四个构造方法中的一个。你需要指定 IP 地址和服务器套接字将要进行监听的端口号。通常,IP 地址将会是 127.0.0.1,也就是说,服务器套接字将会监听本地机器。服务器套接字正在监听的 IP 地址被称为是绑定地址。服务器套接字的另一个重要的属性是 backlog,这是服务器套接字开始拒绝传入的请求之前,传入的连接请求的最大队列长度。</p> 
    <p><strong>public ServerSocket(int port, int backLog, InetAddress bindingAddress)</strong> 是 <strong>ServerSocket</strong>最为常用的构造方法,绑定地址必须是 <code>java.net.InetAddress</code> 的一个实例,通常我们可以使用<code>InetAddress.getByName("127.0.0.1");</code> 构造一个实例。一旦你有一个 <strong>ServerSocket</strong> 实例,你可以让它在绑定地址和服务器套接字正在监听的端口上等待传入的连接请求。你可以通过调用 <strong>ServerSocket</strong> 类的 <strong>accept</strong> 方法做到这点。这个方法只会在有连接请求时才会返回,并且返回值是一个 <strong>Socket</strong> 类的实例。</p> 
    <h3><a name="t8"></a><a id="21ServerSocketHTTPServer_174"></a>2.1、使用ServerSocket构建简单HTTPServer</h3> 
    <p>我们将构建三个类用于组装一个简易的<strong>HTTP Server</strong>,<strong>HttpServer</strong>类用于接受外来<strong>HTTP</strong>请求,通过<strong>accept</strong>方法获取<strong>Socket</strong>实例,并将<strong>InputStream</strong>和<strong>OutputStream</strong> 封装成<strong>HttpRequest</strong>对象和<strong>HttpResone</strong>对象。<strong>HttpRequest</strong>用于解析请求信息(<code>请求地址</code>、<code>请求头</code>、<code>请求参数</code>)等,并将这些信息打印到控制台。而<strong>HttpResone</strong>用于对不同的请求地址,给与不同的响应信息,并将这些响应信息返还给客户端,当客户的请求地址是<code>/HELLO</code>时,将响应<code>Hello, nice to meet</code>给客户端,否则响应<code>Sorry, no corresponding resources found</code>。当请求地址是<code>/SHUTDOWN</code>时,服务器将会被关闭。</p> 
    <p><strong>HttpServer</strong>代码如下:</p> 
    <pre data-index="4" class="set-code-hide prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">InputStream</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">OutputStream</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>net<span class="token punctuation">.</span></span><span class="token class-name">InetAddress</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>net<span class="token punctuation">.</span></span><span class="token class-name">ServerSocket</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>net<span class="token punctuation">.</span></span><span class="token class-name">Socket</span></span><span class="token punctuation">;</span>
    
    <span class="token comment">/**
     * @Author: Greyfus
     * @Create: 2024-08-06 21:21
     * @Version: 1.0.0
     * @Description:HTTP 服务器 Demo
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HttpServer</span> <span class="token punctuation">{<!-- --></span>
    
        <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">String</span> <span class="token constant">SHUTDOWN</span> <span class="token operator">=</span> <span class="token string">"/SHUTDOWN"</span><span class="token punctuation">;</span> <span class="token comment">//关机指令</span>
    
        <span class="token comment">// the shutdown command received</span>
        <span class="token keyword">private</span> <span class="token keyword">boolean</span> shutdown <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    
        <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token class-name">HttpServer</span> httpServer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            httpServer<span class="token punctuation">.</span><span class="token function">startServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//启动服务器</span>
        <span class="token punctuation">}</span>
    
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">startServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token class-name">ServerSocket</span> serverSocket <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
            <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
                serverSocket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ServerSocket</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token class-name">InetAddress</span><span class="token punctuation">.</span><span class="token function">getByName</span><span class="token punctuation">(</span><span class="token string">"127.0.0.1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span>shutdown<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token class-name">Socket</span> socket <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
                <span class="token class-name">InputStream</span> input <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
                <span class="token class-name">OutputStream</span> output <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
                <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
                    socket <span class="token operator">=</span> serverSocket<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//等待获取连接</span>
                    input <span class="token operator">=</span> socket<span class="token punctuation">.</span><span class="token function">getInputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    output <span class="token operator">=</span> socket<span class="token punctuation">.</span><span class="token function">getOutputStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token class-name">HttpRequest</span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpRequest</span><span class="token punctuation">(</span>input<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    request<span class="token punctuation">.</span><span class="token function">parseRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//解析请求</span>
    
                    <span class="token class-name">HttpResponse</span> response <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpResponse</span><span class="token punctuation">(</span>output<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    response<span class="token punctuation">.</span><span class="token function">setRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    response<span class="token punctuation">.</span><span class="token function">loadStaticResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    socket<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    shutdown <span class="token operator">=</span> request<span class="token punctuation">.</span><span class="token function">getUri</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span><span class="token constant">SHUTDOWN</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                    e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">continue</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code></pre> 
    <p><strong>HttpRequest</strong>代码如下:</p> 
    <pre data-index="5" class="set-code-hide prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">InputStream</span></span><span class="token punctuation">;</span>
    
    <span class="token comment">/**
     * @Author: Greyfus
     * @Create: 2024-08-06 21:27
     * @Version: 1.0.0
     * @Description: 用于处理请求信息
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HttpRequest</span> <span class="token punctuation">{<!-- --></span>
    
        <span class="token keyword">private</span> <span class="token class-name">InputStream</span> input<span class="token punctuation">;</span><span class="token comment">//记录输入流</span>
        <span class="token keyword">private</span> <span class="token class-name">String</span> uri<span class="token punctuation">;</span> <span class="token comment">//记录请求地址</span>
    
        <span class="token keyword">public</span> <span class="token class-name">HttpRequest</span><span class="token punctuation">(</span><span class="token class-name">InputStream</span> input<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>input <span class="token operator">=</span> input<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    
        <span class="token comment">/**
         * 解析请求
         */</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">parseRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token class-name">StringBuffer</span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuffer</span><span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">int</span> i<span class="token punctuation">;</span>
            <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> buffer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token number">2048</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
            <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
                i <span class="token operator">=</span> input<span class="token punctuation">.</span><span class="token function">read</span><span class="token punctuation">(</span>buffer<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                i <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> j<span class="token operator"><</span>i<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                request<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">)</span> buffer<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"解析请求信息如下:\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"======================================"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"======================================"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            uri <span class="token operator">=</span> <span class="token function">parseUri</span><span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    
        <span class="token comment">/**
         * 解析请求路径
         * @param requestString
         * @return
         */</span>
        <span class="token keyword">private</span> <span class="token class-name">String</span> <span class="token function">parseUri</span><span class="token punctuation">(</span><span class="token class-name">String</span> requestString<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">int</span> index1<span class="token punctuation">,</span> index2<span class="token punctuation">;</span>
            index1 <span class="token operator">=</span> requestString<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token char">' '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>index1 <span class="token operator">!=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                index2 <span class="token operator">=</span> requestString<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token char">' '</span><span class="token punctuation">,</span> index1 <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>index2 <span class="token operator">></span> index1<span class="token punctuation">)</span>
                    <span class="token keyword">return</span> requestString<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>index1 <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> index2<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    
        <span class="token comment">/**
         * 返回请求地址
         * @return uri
         */</span>
        <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getUri</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">return</span> uri<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code></pre> 
    <p><strong>HttpResponse</strong>代码如下:</p> 
    <pre data-index="6" class="set-code-hide prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
    <span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">OutputStream</span></span><span class="token punctuation">;</span>
    
    <span class="token comment">/**
     * @Author: Greyfus
     * @Create: 2024-08-06 21:31
     * @Version: 1.0.0
     * @Description: 响应信息处理
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HttpResponse</span> <span class="token punctuation">{<!-- --></span>
    
        <span class="token class-name">HttpRequest</span> request<span class="token punctuation">;</span>
        <span class="token class-name">OutputStream</span> output<span class="token punctuation">;</span>
    
        <span class="token keyword">public</span> <span class="token class-name">HttpResponse</span><span class="token punctuation">(</span><span class="token class-name">OutputStream</span> output<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>output <span class="token operator">=</span> output<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setRequest</span><span class="token punctuation">(</span><span class="token class-name">HttpRequest</span> request<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>request <span class="token operator">=</span> request<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    
        <span class="token comment">/**
         * 加载静态资源
         * 如果访问路径是HELLO,则响应 HELLO! Welcome!
         * 否则响应404 错误
         */</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">loadStaticResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{<!-- --></span>
    
            <span class="token keyword">if</span> <span class="token punctuation">(</span>request<span class="token punctuation">.</span><span class="token function">getUri</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equalsIgnoreCase</span><span class="token punctuation">(</span><span class="token string">"/HELLO"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token class-name">String</span> successMessage <span class="token operator">=</span> <span class="token string">"HTTP/1.1 200 ok\n"</span> <span class="token operator">+</span>
                        <span class="token string">"Content-Type: text/html\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"Content-Length: 24\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"<h1>Hello, nice to meet you</h1>"</span><span class="token punctuation">;</span>
                output<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>successMessage<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                <span class="token class-name">String</span> errorMessage <span class="token operator">=</span> <span class="token string">"HTTP/1.1 404 File Not Found\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"Content-Type: text/html\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"Content-Length: 48\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"\r\n"</span> <span class="token operator">+</span>
                        <span class="token string">"<h1>Sorry, no corresponding resources found</h1>"</span><span class="token punctuation">;</span>
                output<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>errorMessage<span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    
    <span class="token punctuation">}</span>
    
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code></pre> 
    <p>使用浏览器演示结果:<br> <img src="https://1000bd.com/contentImg/2024/09/08/a5e4b93844e2bf43.png" alt="在这里插入图片描述"><br> <img src="https://1000bd.com/contentImg/2024/09/08/70e3ec4b7691f19f.png" alt="在这里插入图片描述"><br> 控制台输出结果:<br> <img src="https://1000bd.com/contentImg/2024/09/08/950b50053cdd28f6.png" alt="在这里插入图片描述"></p> 
    <hr>
                    </div>
                        </div>
                    </li>
    
                    <li class="list-group-item ul-li">
    
                        <b>相关阅读:</b><br>
                        <nobr>
    <a href="/Article/Index/1302836">医学影像相关开源数据集资源汇总</a>                            <br />
    <a href="/Article/Index/1265435">Django实现音乐网站 ⒃</a>                            <br />
    <a href="/Article/Index/1711939">数据结构复习笔记6.2:图的存储和遍历</a>                            <br />
    <a href="/Article/Index/1293073">网络安全进阶学习第十九课——CTF之密码学</a>                            <br />
    <a href="/Article/Index/1053656">自动化测试和测试自动化你分的清楚吗?</a>                            <br />
    <a href="/Article/Index/1145949">uva 11729 Commando War(贪心算法)</a>                            <br />
    <a href="/Article/Index/867370">PTA 7-185 组个最小数</a>                            <br />
    <a href="/Article/Index/1262015">puppeteer常规操作代码段</a>                            <br />
    <a href="/Article/Index/1303014">bloaty</a>                            <br />
    <a href="/Article/Index/1358905">【计算机网络笔记】什么是计算机网络?</a>                            <br />
                        </nobr>
                    </li>
                    <li class="list-group-item from-a mb-2">
                        原文地址:https://blog.csdn.net/qq_43600166/article/details/140909223
                    </li>
    
                </ul>
            </div>
    
            <div class="col-lg-4 col-sm-12">
                <ul class="list-group" style="word-break:break-all;">
                    <li class="list-group-item ul-li-bg" aria-current="true">
                        最新文章
                    </li>
                    <li class="list-group-item ul-li">
                        <nobr>
    <a href="/Article/Index/1484446">攻防演习之三天拿下官网站群</a>                            <br />
    <a href="/Article/Index/1515268">数据安全治理学习——前期安全规划和安全管理体系建设</a>                            <br />
    <a href="/Article/Index/1759065">企业安全 | 企业内一次钓鱼演练准备过程</a>                            <br />
    <a href="/Article/Index/1485036">内网渗透测试 | Kerberos协议及其部分攻击手法</a>                            <br />
    <a href="/Article/Index/1877332">0day的产生 | 不懂代码的"代码审计"</a>                            <br />
    <a href="/Article/Index/1887576">安装scrcpy-client模块av模块异常,环境问题解决方案</a>                            <br />
    <a href="/Article/Index/1887578">leetcode hot100【LeetCode 279. 完全平方数】java实现</a>                            <br />
    <a href="/Article/Index/1887512">OpenWrt下安装Mosquitto</a>                            <br />
    <a href="/Article/Index/1887520">AnatoMask论文汇总</a>                            <br />
    <a href="/Article/Index/1887496">【AI日记】24.11.01 LangChain、openai api和github copilot</a>                            <br />
                        </nobr>
                    </li>
                </ul>
    
                <ul class="list-group pt-2" style="word-break:break-all;">
                    <li class="list-group-item ul-li-bg" aria-current="true">
                        热门文章
                    </li>
                    <li class="list-group-item ul-li">
                        <nobr>
    <a href="/Article/Index/888177">十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!</a>                            <br />
    <a href="/Article/Index/797680">奉劝各位学弟学妹们,该打造你的技术影响力了!</a>                            <br />
    <a href="/Article/Index/888183">五年了,我在 CSDN 的两个一百万。</a>                            <br />
    <a href="/Article/Index/888179">Java俄罗斯方块,老程序员花了一个周末,连接中学年代!</a>                            <br />
    <a href="/Article/Index/797730">面试官都震惊,你这网络基础可以啊!</a>                            <br />
    <a href="/Article/Index/797725">你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法</a>                            <br />
    <a href="/Article/Index/797702">心情不好的时候,用 Python 画棵樱花树送给自己吧</a>                            <br />
    <a href="/Article/Index/797709">通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!</a>                            <br />
    <a href="/Article/Index/797716">13 万字 C 语言从入门到精通保姆级教程2021 年版</a>                            <br />
    <a href="/Article/Index/888192">10行代码集2000张美女图,Python爬虫120例,再上征途</a>                            <br />
                        </nobr>
                    </li>
                </ul>
    
            </div>
        </div>
    </div>
    <!-- 主体 -->
    
    
        <!--body结束-->
        <!--这里是footer模板-->
        
        <!--footer-->
    <nav class="navbar navbar-inverse navbar-fixed-bottom">
        <div class="container">
            <div class="row">
                <div class="col-md-12">
                    <div class="text-muted center foot-height">
                        Copyright © 2022 侵权请联系<a href="mailto:2656653265@qq.com">2656653265@qq.com</a>   
                        <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2022015340号-1</a>
                    </div>
                    <div style="width:300px;margin:0 auto; padding:0px 5px;">
                        <a href="/regex.html">正则表达式工具</a>
                        <a href="/cron.html">cron表达式工具</a>
                        <a href="/pwdcreator.html">密码生成工具</a>
                    </div>
                    <div style="width:300px;margin:0 auto; padding:5px 0;">
                        <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010502049817" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;">
                        <img src="" style="float:left;" /><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">京公网安备 11010502049817号</p></a>
                    </div>
                </div>
            </div>
        </div>
      
    </nav>
    <!--footer-->
    
        <!--footer模板结束-->
    
        <script src="/js/plugins/jquery/jquery.js"></script>
        <script src="/js/bootstrap.min.js"></script>
    
        <!--这里是scripts模板-->
        
    
        
     
    
    
        <!--scripts模板结束-->
    
    </body>
    </html>