<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Cyh的博客

    Email:kissyan4916@163.com
    posts - 26, comments - 19, trackbacks - 0, articles - 220

    網絡編程>>HTTP服務器

    Posted on 2009-12-12 16:22 啥都寫點 閱讀(334) 評論(0)  編輯  收藏 所屬分類: J2SE
         與一般的Socket編程一樣,服務器端需要在某個端口上開啟一個ServerSocket,以等待、接受客戶端的請求。
         采用多線程技術,支持多用戶同時訪問,對于每一個請求,都用一個線程專門去處理。
         客戶端發送給服務器端的HTTP請求遵循一定的格式,服務器端需要根據HTTP請求確定請求的類型以及請求的文件名,這些信息都存儲在請求消息的第一行中。比如,用戶瀏覽器地址欄中輸入:" http://localhost:80/test/hehe.htm ",那么產生的請求的第一行便是"GET/test/hehe.htm  HTTP/1.1"         Socket的getInetAddress方法能獲得客戶端的網絡地址信息,包括IP和端口號。
         在給客戶端發送響應消息時,也要按照HTTP協議,給響應消息添加頭信息,然后將被請求文件的字節數組添加到頭信息的后面,頭信息的第一行為為"HTTP/1.1 200 0K" 表示"HTTP協議的版本為1.1,處理請求成功",頭信息的第一行為"HTTP/1.1 400"表示"HTTP協議的版本為1.1,處理請求失敗,文件沒找到"。


    /**
     * HTTP的服務器,接收來自客戶端的HTTP請求。
     * 將要發布的HTML文件放置在工程的根目錄下,
     * 然后在瀏覽器中輸入類似"
    http://localhost:80/"的網址,
     * 將能夠顯示網頁的內容。
     
    */

    public class HttpServer {
        
    // 服務器名和端口
        String serverName;
        
    int serverPort;

        
    // 定義server的名字、版本號、端口 
        public HttpServer(String name, int port) {
            
    this.serverName = name;
            
    this.serverPort = port;
        }


        
    public void run() {
            
    // 顯示名字和端口號 
            System.out.println("HttpServer: " + serverName + "" + serverPort);
            
    try {
                
    // 得到服務器監聽端口 
                ServerSocket server = new ServerSocket(serverPort);
                
    do {
                    
    // 等待連接請求 
                    Socket client = server.accept();
                    
    // 為連接請求分配一個線程 
                    (new HTTPServerThread(client)).start();
                }
     while (true);
            }
     catch (Exception e) {
                e.printStackTrace();
                System.exit(
    1);
            }

        }

        
    // 構造一個server,并運行 
        public static void main(String args[]) {
            HttpServer server 
    = new HttpServer("MyHTTPServer"80);
            server.run();
        }

    }


    /**
     * 處理HTTP請求的線程,一個HTTP請求對應一個線程
     
    */

    class HTTPServerThread extends Thread {
        
    // 服務器與客戶端之間的socket
        Socket client;
        
    public HTTPServerThread(Socket client) {
            
    this.client = client;
        }


        
    public void run() {
            
    try {
                
    // 顯示連接信息
                describeConnectionInfo(client);
                
    // 獲取流向到客戶端的輸出流
                BufferedOutputStream outStream = new BufferedOutputStream(client
                        .getOutputStream());
                
    // 獲取來自客戶端的輸入流 
                HTTPInputStream inStream = new HTTPInputStream(client
                        .getInputStream());
                
    // 得到客戶端的請求頭(自定義類) 
                HTTPRequest request = inStream.getRequest();
                
    // 顯示頭信息 
                request.log();
                
    // 目前只處理GET請求 
                if (request.isGetRequest()){
                    processGetRequest(request, outStream);
                }

                System.out.println(
    "Request completed. Closing connection.");
                
    //關閉socket 
                client.close();
            }
     catch (IOException e) {
                System.out.println(
    "IOException occurred .");
                e.printStackTrace();
            }

        }


        
    // 顯示socket連接信息
        void describeConnectionInfo(Socket client) {
            
    //客戶端的主機名 
            String destName = client.getInetAddress().getHostName();
            
    //客戶端的IP地址 
            String destAddr = client.getInetAddress().getHostAddress();
            
    //客戶端的端口 
            int destPort = client.getPort();
            
    //打印信息,表示客戶端已經連接到本服務器上 
            System.out.println("Accepted connection to " + destName + " ("
                    
    + destAddr + ")" + " on port " + destPort + ".");
        }


        
    // 處理GET請求 
        void processGetRequest(HTTPRequest request, BufferedOutputStream outStream)
                
    throws IOException {
            
    // 獲得客戶端要get的文件名
            String fileName = request.getFileName();
            File file 
    = new File(fileName);
            
    // 如果文件存在,則將文件內容發送到socket的輸出流,即客戶端。 
            if (file.exists()){
                sendFile(outStream, file);
            }
     else {
                System.out.println(
    "File " + file.getCanonicalPath()
                        
    + " does not exist.");
            }

        }


        
    //  發送文件內容到客戶端,這里以HTTP 1.1的協議實現的
        void sendFile(BufferedOutputStream out, File file) {
            
    try {
                
    // 將文件內容全部讀入到一個字節數組中
                DataInputStream in = new DataInputStream(new FileInputStream(file));
                
    int len = (int) file.length();
                
    byte buffer[] = new byte[len];
                
    // 完全讀取,然后關閉文件流
                in.readFully(buffer);
                in.close();
                
                
    // 寫到socket的輸出流中
                out.write("HTTP/1.1 200 OK\r\n".getBytes());
                out.write((
    "Content-Length: " + buffer.length + "\r\n").getBytes());
                out.write(
    "Content-Type: text/HTML\r\n\r\n".getBytes());
                out.write(buffer);
                out.flush();
                out.close();
                
    // 寫文件內容結束,log信息
                System.out.println("File sent: " + file.getCanonicalPath());
                System.out.println(
    "Number of bytes: " + len);
            }
     catch (Exception e) {
                
    try {
                    
    // 發送失敗
                    out.write(("HTTP/1.1 400 " + "No can do" + "\r\n").getBytes());
                    out.write(
    "Content-Type: text/HTML\r\n\r\n".getBytes());
                }
     catch (IOException ioe) {
                }

                System.out.println(
    "Error retrieving " + file);
            }

        }

    }


    /**
     * 實現讀客戶端請求的幫助類
     
    */

    class HTTPInputStream extends FilterInputStream {
        
    public HTTPInputStream(InputStream in) {
            
    super(in);
        }


        
    // 讀一行,當輸入流中沒有數據,或者讀到"\r\n"時,一行結束。 
        public String readLine() throws IOException {
            StringBuffer result 
    = new StringBuffer();
            
    boolean finished = false;
            
    //'\r'為回車符,值為13,'\n'為換行符,值為10
            
    // cr變量表示是否已經讀到換行符
            boolean cr = false;
            
    do {
                
    int ch = -1;
                
    // 讀一個字節
                ch = read();
                
    if (ch == -1){
                    
    return result.toString();
                }

                result.append((
    char) ch);
                
    //去掉最后的'\r\n' 
                if (cr && (ch == 10)) {
                    result.setLength(result.length() 
    - 2);
                    
    return result.toString();
                }

                
    //讀到回車符,設置標識 
                if (ch == 13){
                    cr 
    = true;
                }
     else {
                    cr 
    = false;
                }

            }
     while (!finished);
            
    return result.toString();
        }


        
    // 得到所有的請求 
        public HTTPRequest getRequest() throws IOException {
            HTTPRequest request 
    = new HTTPRequest();
            String line;
            
    do {
                
    // 依次讀取
                line = readLine();
                
    //將請求填入容器 
                if (line.length() > 0){
                    request.addLine(line);
                }
     else {
                    
    break;
                }

            }
     while (true);
            
    // 返回
            return request;
        }

    }


    // 客戶端請求的封裝類 
    class HTTPRequest {
        
    // 請求的數據,按行存儲
        Vector lines = new Vector();
        
    public HTTPRequest() {
        }


        
    public void addLine(String line) {
            lines.addElement(line);
        }


        
    // 判斷是否是Get請求 
        boolean isGetRequest() {
            
    if (lines.size() > 0{
                
    // 獲取請求內容的第一行,如果頭三個字符是"GET",則為Get請求
                String firstLine = (String) lines.elementAt(0);
                
    if (firstLine.length() > 0){
                    
    if (firstLine.substring(03).equalsIgnoreCase("GET")){
                        
    return true;
                    }

                }

            }

            
    return false;
        }


        
    // 從請求中解析到文件名 
        
    // 一般第一行的消息如此類格式:"GET /hehe.htm HTTP/1.1"
        /**
         * 從請求中解析到文件名,只需要處理第一行即可。
         * 第一行的格式有如下幾種:
         * (1)如果請求的URL為"
    http://localhost:80/test/hehe.htm",
         * 則第一行的內容為"GET /test/hehe.htm HTTP/1.1"。
         * (2)如果請求的URL為"
    http://localhost:80",
         * 則第一行的內容為"GET HTTP/1.1",此時應該找默認的html文件,如index.htm
         * (3)如果請求的URL為"
    http://localhost:80/test",
         * 則第一行的內容為"GET /test/ HTTP/1.1",此時應該找test目錄下默認的html文件
         
    */

        String getFileName() 
    {
            
    if (lines.size() > 0{
                
    //得到vector中第一個元素 
                String firstLine = (String) lines.elementAt(0);

                System.out.println(
    "firstLine:  " + firstLine);
                
    //根據http消息格式得到文件名
                String fileName = firstLine.substring(firstLine.indexOf(" "+ 1);
                
    int n = fileName.indexOf(" ");
                
    //URL在兩個空格之間 
                if (n != -1){
                    fileName 
    = fileName.substring(0, n);
                }


                
    //去掉第一個'/' 
                try {
                    
    if (fileName.charAt(0== '/'){
                        fileName 
    = fileName.substring(1);
                    }

                }
     catch (StringIndexOutOfBoundsException ex) {
                }


                
    //默認首頁,這里認為index.htm為默認的首頁
                
    //類似于'http://localhost:80'的情況 
                if (fileName.equals("")){
                    fileName 
    = "index.htm";
                }

                
    //類似于'http://localhost:80/download/'的情況 
                if (fileName.charAt(fileName.length() - 1== '/'){
                    fileName 
    += "index.htm";
                }

                System.out.println(
    "fileName:  " + fileName);
                
    return fileName;
            }
     else {
                
    return "";
            }

        }


        
    // 顯示請求信息 
        void log() {
            System.out.println(
    "Received the following request:");
            
    for (int i = 0; i < lines.size(); ++i){
                System.out.println((String) lines.elementAt(i));
            }

        }

    }


                                                                                                           --    學海無涯
            

    主站蜘蛛池模板: 亚洲AV无码久久精品色欲| 成人黄网站片免费视频| 精品亚洲成a人片在线观看| 男人的天堂亚洲一区二区三区| 国产三级在线免费| 水蜜桃视频在线观看免费| 亚洲成人激情小说| 精品亚洲国产成AV人片传媒| 亚洲熟妇丰满多毛XXXX| 免费无遮挡无码永久在线观看视频| 免费99精品国产自在现线| 伊人久久免费视频| a级毛片在线免费看| 国产va免费精品| 成人免费网站视频www| 日本亚洲欧美色视频在线播放| 亚洲深深色噜噜狠狠网站| 亚洲嫩草影院在线观看| 亚洲精品免费在线观看| 亚洲AV午夜成人影院老师机影院| 久久亚洲精品无码观看不卡| 亚洲国产激情一区二区三区| 俄罗斯极品美女毛片免费播放| 国产色婷婷精品免费视频| 在线免费观看中文字幕| 成人免费午夜在线观看| 免费可以在线看A∨网站| 成人免费午夜视频| 成年人视频在线观看免费| 成年人免费网站在线观看| 成人毛片18岁女人毛片免费看| 久久精品免费一区二区喷潮| 久久笫一福利免费导航| 国国内清清草原免费视频99| 全免费毛片在线播放| 嫖丰满老熟妇AAAA片免费看| 国产精品1024永久免费视频| 无码日韩精品一区二区免费| 最近中文字幕无吗免费高清| 日韩高清免费观看| 亚洲第一页日韩专区|