2013/12/16

[Java] Web Server撰寫

網路的連線可以分成TCP以及UDP連線,TCP是連線導向且為可靠式,傳送上以每個byte為單位,有重傳機制確保資料可以正確地送到目的IP位址,適合用在傳輸文字、各種檔案、HTTP網路連線等這種不能損失封包的資料上,缺點是較無效率;而UDP則是非連線導向且為不可靠式,傳送上以每個packet為單位,因為不保證資料都能夠送達目的地,沒有重傳機制,速度較快,適合用在傳輸影音串流上,缺點是封包會有損失。

網路的連線可以從Physical layer -> Data Link layer -> Network layer -> Transport layer -> Application layer來探討,舉HTTP這個在user上的application為例子,是透過網路連線,經過電腦的MAC和IP位址,還有IP port number 80,最後透過HTTP的protocol來連線溝通。



舉例來說,我們使用電腦的瀏覽器輸入https://www.google.com.tw/,其實就是在連線Google server的port 80,電腦的browser會送一個request給google,然後google server會根據browser的request來回應一個response給browser,最後browser會顯示把資料在網頁上,這就是一般的瀏覽動作。因為網頁上的資料不能夠有傳送封包損失,因此HTTP是採用TCP連線。

HTTP的protocol主要分為兩個,request以及response,。
1.request message

GET /somedir/page.html HTTP/1.1   <--- request line
Host: www.someschool.edu           <--- header lines
User-agent: Mozilla/4.0
Connection: close
Accept-language: fr                <---
                                    <--- blank line, carriage return
2.response message

HTTP/1.1 200 OK              <--- status line,200為連線成功,404為找不到此網頁
Connection close             <--- header lines
Content-Length: 6821
Content-Type: text/html      <---
                            <--- blank line, carriage return
data data data ...            <--- data
值得注意的地方是header lines會用一個空白行與底下的資料隔開。

所以我們可以利用JAVA的TCP來架一個Web Server,使用port 80來連線,然後使用瀏覽器輸入server的IP,傳送request給server,然後server再根據請求的檔案名稱,傳送response給瀏覽器,這樣就完成一個簡單的HTTP的WebServer程式了。

底下為程式碼範例
瀏覽器輸入http://127.0.0.1的時候,利用HTTP的response格式,傳送字串"Welcome to the Java WebServer";當瀏覽器傳送http://127.0.0.1/Yushan.jpg則傳送圖檔Yusuan.jpg給瀏覽器。
webServer.java
/*
* webServer.java
* HTTP Protocol
* TCP/IP 127.0.0.1, Port 80
*/

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;

public class webServer {
    public static void main(String[] args) throws Exception {

        String requestMessageLine;
        String fileName;
        System.out.println("Web Server Starting on Port 80");
        ServerSocket s = new ServerSocket(80);


        System.out.println("Waiting for Connecting...");
        while(true) {
            Socket serverSocket = s.accept();
            System.out.println("Connection, sending data.");
            BufferedReader in = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(serverSocket.getOutputStream());

            requestMessageLine = in.readLine();
            StringTokenizer tokenizedLine = new StringTokenizer(requestMessageLine);

            if(tokenizedLine.nextToken().equals("GET")) {
                fileName = tokenizedLine.nextToken();
                if(fileName.startsWith("/")==true)
                    fileName = fileName.substring(1);

                if(fileName.endsWith(".jpg")) {
                    File file = new File(fileName);
                    int numOfBytes = (int) file.length();

                    FileInputStream inFile = new FileInputStream(fileName);
                    byte[] fileInBytes = new byte[numOfBytes];
                    inFile.read(fileInBytes);

                    outToClient.writeBytes("HTTP/1.0 200 OK\r\n");
                    outToClient.writeBytes("Content-Type: image/jpeg\r\n");
                    outToClient.writeBytes("Content-Length: "+numOfBytes+"\r\n");
                    outToClient.writeBytes("\r\n");
                    outToClient.write(fileInBytes, 0, numOfBytes);
                    inFile.close();
                    System.out.println("Sending data completely.");
                }
                else {
                    outToClient.writeBytes("HTTP/1.0 200 OK\r\n");
                    outToClient.writeBytes("Content-Type: text/html\r\n");
                    outToClient.writeBytes("\r\n");
                    outToClient.writeBytes("<H1>Welcome to the Java WebServer</H1>\r\n");
                    System.out.println("Sending data completely.");
                }
            serverSocket.close();
            outToClient.flush();
        }
        else
            System.out.println("Bad Request Message");
        }
    }
}
執行結果如下
WebServer

瀏覽器輸入http://127.0.0.1

瀏覽器輸入http://127.0.0.1/Yushan.jpg

這樣就簡單的架設一個Java的Web Server了。

2 則留言: