無線&移動互聯網技術研發

          換位思考·····
          posts - 19, comments - 53, trackbacks - 0, articles - 283
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          利用java構建http服務器(摘)

          Posted on 2009-12-27 00:12 Gavin.lee 閱讀(431) 評論(0)  編輯  收藏 所屬分類: java SE & EE

          web服務器大家都會用,可是它的實現原理是到底如何呢,其實只要讀一下http協議,大家基本也能開發出一個簡單的web服務器出來了。

          web請求分為如下幾步

          1. 瀏覽器向服務建立TCP/IP連接,Java中通過java.net.Socket實現

          2. Web瀏覽器向Web服務器發送請求命令。通過Socket的輸出流向服務器寫如下信息:

            GET /uri HTTP/1.1,很顯示第一部分為請求的方法,第二部分為請求的URI,第三部分為請求的協議

          3. Web瀏覽器發送請求頭信息。這部分包括瀏覽器的版本信息,接受的格式、編碼等,還有非常有用的一個數據Cookie也是在這里發送的。

          4. 頭信息發送完后,發送一個空格表示結束,如果是post請求,則繼續發送Post正文。

          5. Web服務器做出應答,如返回"HTTP/1.1 200  OK",表示請求成功,或者返回404,500等狀態信息表示找不到頁面或服務器錯誤。

          6. Web服務器發送應答頭信息,這部分表示了返回的內容類型(如是gif還是exe還是html等),返回的數據的編碼,長度,當然還有Cookie(通過set-Cookie來發送)

          7. 在發送完應答頭后,則發送一個空行。如果有響應正文,則在后面繼續發送響應內容。

          8. 關閉TCP/IP連接

          以下代碼簡單的模擬了這一過程。

          客戶端代碼:

          package com.yixun.wap;

          import java.io.BufferedReader;
          import java.io.InputStream;
          import java.io.InputStreamReader;
          import java.io.OutputStream;
          import java.net.Socket;

          public class Client {
              Socket socket 
          = null;
              
              
          // 1. 建立到服務器的連接
              private void connect() throws Exception {
                  socket 
          = new Socket("serverName"80);
              }


              
          // 2. 發送請求命令
              private void sendRequestCommand() throws Exception {
                  OutputStream os 
          = socket.getOutputStream();
                  os.write(
          "GET /index.html HTTP/1.1\n".getBytes());
              }


              
          // 3. 發送請求頭信息
              private void sendHeader() throws Exception {
                  OutputStream os 
          = socket.getOutputStream();
                  os.write((
          "Accept: */*\n"
                                  
          + "Accept-Language: zh-cn;q=0.5\n"
                                  
          + "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; CIBA; .NET CLR 2.0.50727)\n"
                                  
          + "Host: 192.168.1.110\n" + "Connection: Keep-Alive\n"
                                  
          + "\n").getBytes());
                  os.flush();
              }


              
          // 4. 檢測服務器發送回來的響應
              private void getResponse() throws Exception {
                  InputStream is 
          = socket.getInputStream();
                  
          while (is.available() == 0{
                      Thread.sleep(
          10);
                  }

                  BufferedReader br 
          = new BufferedReader(new InputStreamReader(is,
                          
          "utf-8"));
                  String line 
          = null;
                  
          while ((line = br.readLine()) != null{
                      System.out.println(line);
                  }

              }

          }


          服務器代碼如下:
          package com.yixun.wap;

          import java.io.FileInputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.net.ServerSocket;
          import java.net.Socket;

          public class Server {
              
          private ServerSocket server;

              
          public void start() throws Exception {
                  server 
          = new ServerSocket(80);// 監聽80端口
                  accept();
              }


              
          private void accept() {
                  
          new Thread() {
                      
          public void run() {
                          
          while (true{
                              
          try {
                                  System.out.println(
          "accept");
                                  Socket socket 
          = server.accept();
                                  System.out.println(
          "new client.");
                                  processRequest(socket);
                              }
           catch (IOException e) {
                                  e.printStackTrace();
                              }

                          }

                      }

                  }
          .start();
              }


              
          private void processRequest(Socket socket) {
                  
          new RequestProcessor(socket).start();
              }


              
          // 將每個請求用一個單獨的線程來進行處理,這樣可以實現多個請求的并發處理功能
              private class RequestProcessor extends Thread {
                  Socket socket;

                  RequestProcessor(Socket socket) 
          {
                      
          this.socket = socket;
                  }


                  
          public void run() {
                      
          try {
                          InputStream is 
          = socket.getInputStream();
                          
          while (is.available() == 0{
                              Thread.sleep(
          10); // 檢測客戶端是否發送過來了請求數據
                          }


                          
          while (is.available() > 0{
                              System.out.print((
          char) is.read());// 打印發送過來的所有數據,可以保存起來以做進一步的處理
                          }


                          String info 
          = "HTTP/1.1 200 OK\n"
                                  
          + "Server: Apache-Coyote/1.1\n"
                                  
          + "Content-Type: text/html;charset=utf-8\n"
                                  
          + "Content-Length: 1021\n"
                                  
          + "Date: Wed, 09 Dec 2009 05:00:27 GMT\n" + "\n";
                          OutputStream os 
          = socket.getOutputStream();
                          os.write(info.getBytes(
          "utf-8"));
                          os.flush();

                          FileInputStream fis 
          = new FileInputStream("webRoot/index.html");// 假設用戶請求的是index.html,讀取該文件做為響應
                          byte data[] = new byte[1024 * 10];
                          
          int length = 0;
                          
          while ((length = fis.read(data)) > 0{
                              os.write(data, 
          0, length);
                          }

                          os.flush();
                          os.close();
                      }
           catch (Exception e) {
                          e.printStackTrace();
                      }


                  }

              }

          }


          主站蜘蛛池模板: 四川省| 民丰县| 利津县| 宁国市| 略阳县| 迭部县| 南漳县| 万源市| 攀枝花市| 望奎县| 吴忠市| 十堰市| 民丰县| 台湾省| 安塞县| 苏尼特左旗| 当阳市| 马龙县| 怀宁县| 民县| 安化县| 武穴市| 华亭县| 改则县| 威远县| 象州县| 东平县| 彭泽县| 晋城| 天气| 庆阳市| 乳山市| 丹凤县| 东明县| 安康市| 顺昌县| 克拉玛依市| 黄浦区| 衡阳市| 元氏县| 密山市|