<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          每日一例 | 搞個(gè)大事……手寫簡(jiǎn)易web服務(wù)器

          共 9077字,需瀏覽 19分鐘

           ·

          2021-06-02 02:37

          前言

          已經(jīng)做java開發(fā)好幾年了,但是一直覺得web服務(wù)器是個(gè)很神秘的東西,之前有參考過一個(gè)大佬用netty寫的簡(jiǎn)易版的springboot,但是最后都不了了之了。今天,突然又有了想寫個(gè)web服務(wù)器了,所以就有了今天個(gè)小demo。

          但是demo還是有點(diǎn)問題,就是瀏覽器請(qǐng)求的時(shí)候,服務(wù)端無法響應(yīng),但是把瀏覽器請(qǐng)求終止掉,服務(wù)端開始響應(yīng)了,但是這時(shí)候響應(yīng)結(jié)果已經(jīng)無法傳給瀏覽器了。這個(gè)問題,后期得研究下。

          開整

          今天才真正知道并理解了Tomcat是基于socket實(shí)現(xiàn)的,以前可能看到過相關(guān)博客和文檔,但是一直無法正在理解,想不明白它到底是咋樣通過Socket實(shí)現(xiàn)的,直到今天寫完這個(gè)demo,我發(fā)現(xiàn)突然就想明白了,頓悟的感覺,所以我已經(jīng)決定自己要?jiǎng)邮謱懸粋€(gè)web框架,名字就叫syske-boot,flag先立起來。

          服務(wù)端

          服務(wù)端其實(shí)就是一個(gè)socket服務(wù)端,用于處理客戶端請(qǐng)求。

          public class SyskeCatServer {
              private static final int port = 8080;
              public static void main(String[] args) throws Exception{
                  ServerSocket serverSocket = null;
                  try {
                      serverSocket = new ServerSocket(port);
                      System.out.println("SyskeCatServer is starting……");
                      while (true){
                          Socket accept = serverSocket.accept();
                          InputStream inputStream = accept.getInputStream();
                          OutputStream outputStream = accept.getOutputStream();
                          SimpleHttpServer simpleHttpServer = new SimpleHttpServer();
                          SyskeRequest syskeRequest = new SyskeRequest(inputStream);
                          SyskeResponse syskeResponse = new SyskeResponse(outputStream);
                          simpleHttpServer.doService(syskeRequest, syskeResponse);
                          accept.close();
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                  } finally {
                      serverSocket.close();
                  }
              }
          }

          首先,從serverSocket中分別獲取輸入流和輸出流,這里的SyskeRequest就是對(duì)InputStream的封裝,SyskeResponse就是對(duì)OutputStream的封裝。我們根據(jù)這個(gè)也可以大膽推測(cè),tomcatRequestResponse也是類似的實(shí)現(xiàn)。

          doService方法

          class SimpleHttpServer {

              public void doService(SyskeRequest request, SyskeResponse response) throws Exception {
                  try {
                      byte[] bytes = new byte[1024];
                      int read;
                      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                      while ((read = request.getInputStream().read(bytes)) != -1) {
                          byteArrayOutputStream.write(bytes);
                      }
                      byte[] toByteArray = byteArrayOutputStream.toByteArray();
                      String requestStr = new String(toByteArray);
                      System.out.println(String.format("請(qǐng)求參數(shù):%s", requestStr));
                      String[] split = requestStr.split("\r\n");
                      System.out.println("end");
                      response.write("hello syskeCat");
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }

          SyskeRequest

          這里就是包裝了InputStream

          public class SyskeRequest {
              private InputStream inputStream;

              public InputStream getInputStream() {
                  return inputStream;
              }

              public SyskeRequest(InputStream inputStream) {
                  this.inputStream = inputStream;
              }
          }

          SyskeResponse

          這里就是對(duì)OutputStream簡(jiǎn)單包裝

          public class SyskeResponse {
                  private OutputStream outputStream;

                  public SyskeResponse(OutputStream outputStream) {
                      this.outputStream = outputStream;
                  }

                  //將文本轉(zhuǎn)換為字節(jié)流
                  public void write(String content) throws IOException {
                      StringBuffer httpResponse = new StringBuffer();
                      httpResponse.append("HTTP/1.1 200 OK\n")      //按照HTTP響應(yīng)報(bào)文的格式寫入
                              .append("Content-Type:text/html\n")
                              .append("\r\n")
                              .append("<html><head><link rel=\"icon\" href=\"data:;base64,=\"></head><body>")
                              .append(content)          //將頁(yè)面內(nèi)容寫入
                              .append("</body></html>");
                      outputStream.write(httpResponse.toString().getBytes());      //將文本轉(zhuǎn)為字節(jié)流
                      outputStream.close();
                  }
          }

          測(cè)試

          好了,上面這些就是核心代碼了,是不是很簡(jiǎn)單。我們來運(yùn)行下看看,直接運(yùn)行main方法就行了。服務(wù)端啟動(dòng)了:

          瀏覽器訪問下看看:

          這里瀏覽器一直沒響應(yīng),但是后臺(tái)也沒有收到請(qǐng)求,但是當(dāng)我終止請(qǐng)求后(點(diǎn)擊瀏覽器的x),服務(wù)端收到了請(qǐng)求:

          看下后端收到的socket請(qǐng)求參數(shù),是不是很熟悉:

          請(qǐng)求參數(shù):GET /tfgdfgdf HTTP/1.1
          Host: localhost:8080
          Connection: keep-alive
          Cache-Control: max-age=0
          sec-ch-ua: " Not A;Brand";v="99""Chromium";v="90""Google Chrome";v="90"
          sec-ch-ua-mobile: ?0
          Upgrade-Insecure-Requests: 1
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 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.9
          Sec-Fetch-Site: none
          Sec-Fetch-Mode: navigate
          Sec-Fetch-User: ?1
          Sec-Fetch-Dest: document
          Accept-Encoding: gzip, deflate, br
          Accept-Language: zh-CN,zh;q=0.9
          Cookie: NMTID=00O3GJZgJXpkp8vI0cpmNRliUnGvYkAAAF4sPsi2w

          這不就是瀏覽器的請(qǐng)求頭嗎?里面包括了請(qǐng)求地址、以及客戶端的其他信息。

          如果你想實(shí)現(xiàn)更加請(qǐng)求地址響應(yīng)的需求,只需要解析下請(qǐng)求數(shù)據(jù)就行了,我覺得這些都簡(jiǎn)單了,最難的是從01,就是瀏覽器可以請(qǐng)求后可以收到響應(yīng),我覺得我現(xiàn)在做到了0.5,后面的0.5還需要再研究下。

          總結(jié)

          整體來說,這個(gè)實(shí)例還是比較簡(jiǎn)單的,雖然最后沒有完整地達(dá)到了最終的目的,但是還是有收獲的,至少服務(wù)請(qǐng)求收到了吧,所以從這個(gè)點(diǎn)上講,收獲還是大于預(yù)期的,而且對(duì)我而言還發(fā)現(xiàn)新大陸,只要這個(gè)缺憾,后面再好好摸索下,反正這個(gè)硬砍我啃定了。

          - END -


          瀏覽 48
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉青娱乐 | 国产一区二区三区乱伦 | 亚洲男女视频免费看 | 欧美怡红院视频一区二区三区 | 国产一区二区三区四区五区六区七区 |