<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

    網(wǎng)絡(luò)編程>>HTTP服務(wù)器

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


    /**
     * HTTP的服務(wù)器,接收來(lái)自客戶端的HTTP請(qǐng)求。
     * 將要發(fā)布的HTML文件放置在工程的根目錄下,
     * 然后在瀏覽器中輸入類(lèi)似"
    http://localhost:80/"的網(wǎng)址,
     * 將能夠顯示網(wǎng)頁(yè)的內(nèi)容。
     
    */

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

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


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

        }

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

    }


    /**
     * 處理HTTP請(qǐng)求的線程,一個(gè)HTTP請(qǐng)求對(duì)應(yīng)一個(gè)線程
     
    */

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


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

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

        }


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


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

        }


        
    //  發(fā)送文件內(nèi)容到客戶端,這里以HTTP 1.1的協(xié)議實(shí)現(xiàn)的
        void sendFile(BufferedOutputStream out, File file) {
            
    try {
                
    // 將文件內(nèi)容全部讀入到一個(gè)字節(jié)數(shù)組中
                DataInputStream in = new DataInputStream(new FileInputStream(file));
                
    int len = (int) file.length();
                
    byte buffer[] = new byte[len];
                
    // 完全讀取,然后關(guān)閉文件流
                in.readFully(buffer);
                in.close();
                
                
    // 寫(xiě)到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();
                
    // 寫(xiě)文件內(nèi)容結(jié)束,log信息
                System.out.println("File sent: " + file.getCanonicalPath());
                System.out.println(
    "Number of bytes: " + len);
            }
     catch (Exception e) {
                
    try {
                    
    // 發(fā)送失敗
                    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);
            }

        }

    }


    /**
     * 實(shí)現(xiàn)讀客戶端請(qǐng)求的幫助類(lèi)
     
    */

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


        
    // 讀一行,當(dāng)輸入流中沒(méi)有數(shù)據(jù),或者讀到"\r\n"時(shí),一行結(jié)束。 
        public String readLine() throws IOException {
            StringBuffer result 
    = new StringBuffer();
            
    boolean finished = false;
            
    //'\r'為回車(chē)符,值為13,'\n'為換行符,值為10
            
    // cr變量表示是否已經(jīng)讀到換行符
            boolean cr = false;
            
    do {
                
    int ch = -1;
                
    // 讀一個(gè)字節(jié)
                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();
                }

                
    //讀到回車(chē)符,設(shè)置標(biāo)識(shí) 
                if (ch == 13){
                    cr 
    = true;
                }
     else {
                    cr 
    = false;
                }

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


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

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

    }


    // 客戶端請(qǐng)求的封裝類(lèi) 
    class HTTPRequest {
        
    // 請(qǐng)求的數(shù)據(jù),按行存儲(chǔ)
        Vector lines = new Vector();
        
    public HTTPRequest() {
        }


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


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

                }

            }

            
    return false;
        }


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

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

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


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

                }
     catch (StringIndexOutOfBoundsException ex) {
                }


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

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

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

        }


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

        }

    }


                                                                                                           --    學(xué)海無(wú)涯
            

    主站蜘蛛池模板: 亚洲第一第二第三第四第五第六| 无码国产精品一区二区免费式直播| 亚洲?V无码成人精品区日韩| 精品丝袜国产自在线拍亚洲| 91免费国产自产地址入| 亚洲成在人线av| 中文字幕乱理片免费完整的| 亚洲国产高清在线一区二区三区| 亚洲国产欧美日韩精品一区二区三区 | 精品国产一区二区三区免费| 亚洲精品tv久久久久| 精品久久亚洲一级α| 女人毛片a级大学毛片免费| 亚洲理论片在线观看| 少妇人妻偷人精品免费视频| 亚洲精品中文字幕乱码三区| 阿v免费在线观看| 免费欧洲美女牲交视频| 亚洲AV成人无码网天堂| 好爽…又高潮了毛片免费看| 33333在线亚洲| 无码日韩人妻av一区免费| 91嫩草亚洲精品| 免费福利视频导航| 亚洲精品在线电影| 2021在线永久免费视频| 亚洲精品午夜在线观看| 美女内射毛片在线看免费人动物| 亚洲v高清理论电影| 久久午夜无码免费| 777亚洲精品乱码久久久久久| 久久久久免费看黄a级试看| 久久精品亚洲一区二区| 日韩免费无码视频一区二区三区| 亚洲成人中文字幕| 91免费国产精品| 亚洲国产日韩在线一区| 国产啪精品视频网免费| 亚洲伊人久久大香线蕉AV| 大陆一级毛片免费视频观看i| 亚洲av无码av在线播放|