簡體   English   中英

簡單HTTP服務器中的會話處理

[英]Session handling in simple http server

我正在基於下一個模型編寫一個小的Http Web服務器:

public class HttpServer {

    public static void main(String[] args) throws Throwable {
        ServerSocket ss = new ServerSocket(8080);
        while (true) {
            Socket s = ss.accept();
            System.err.println("Client accepted");
            new Thread(new SocketProcessor(s)).start();
        }
    }

    private static class SocketProcessor implements Runnable {

        private Socket s;
        private InputStream is;
        private OutputStream os;

        private SocketProcessor(Socket s) throws Throwable {
            this.s = s;
            this.is = s.getInputStream();
            this.os = s.getOutputStream();
        }

        public void run() {
            try {
                readInputHeaders();
                writeResponse("<html><body><h1>Hello</h1></body></html>");
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                try {
                    s.close();
                } catch (Throwable t) {
                   t.printStackTrace();
                }
            }
            System.err.println("Client processing finished");
        }

        private void writeResponse(String s) throws Throwable {
            String response = "HTTP/1.1 200 OK\r\n" +
                    "Server: YarServer/2009-09-09\r\n" +
                    "Content-Type: text/html\r\n" +
                    "Content-Length: " + s.length() + "\r\n" +
                    "Connection: close\r\n\r\n";
            String result = response + s;
            os.write(result.getBytes());
            os.flush();
        }

        private void readInputHeaders() throws Throwable {
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            while(true) {
                String s = br.readLine();
                if(s == null || s.trim().length() == 0) {
                    break;
                }
            }
        }
    }
}
  1. 在端口x上運行服務器套接字
  2. 不要acceptwhile
  3. 如果出現新請求,請在新線程中處理請求
  4. 等待另一個請求

但是我該如何實施會議? 是否有任何機制可以將一個會話與另一個會話區分開? 關閉瀏覽器后如何清理會話? 如何保持連接打開?

我不確定保留連接選項是什么意思,但是我想創建一個唯一的(隨機)cookie值並將其發送回客戶端。 這是您的會話ID。 在服務器上,您將此會話ID存儲在某種映射中(ConcurrentHashMap可能是線程安全的一個不錯的選擇)作為鍵,並且任何特定的會話數據都將是value對象的一部分。

當您收到傳入連接時,請檢查其是否提供了具有已知會話ID的cookie。 如果是這樣,則可以從Session HashMap中檢索value對象並將其應用於當前連接。

如果會話ID不存在,則表示它是一個新會話。

通過適當設置cookie的有效時間(即MaxAge的負值),只要關閉瀏覽器會話,就將刪除cookie。

在過去,當php仍然很新,而cgi是主導的“動態Web技術”時,會生成一個臨時文件並告訴客戶端文件名。 持有此文件名的每個請求都將至少更改文件名的最后訪問時間戳,而cron作業將刪除每個早於一定數量的文件。

正如tmarwen所說,在服務器端的會話只是一張地圖。 但是您不需要將其鏈接到線程。 只需將其放入具有ID的另一張地圖中即可。 例如,將coockie用作客戶端(瀏覽器)上的ID持有人。 要保持連接,您可以保持線程活動。 在HTTP / 1.1中,關於這種外觀的更多信息是保持活動機制。 您還需要符合狀態和標頭才能使用HTTP。

只要每個客戶端(瀏覽器)都保持自己的單個連接處於活動狀態(盡管這種情況很少發生),您甚至不需要一個單獨的會話層,因為您的(TCP-)連接是有狀態的,或者換句話說:您的服務器可以基於(接受的)Socket對象在客戶端之間進行區分。

對於所有其他情況,除了使用Cookie之外,只有幾種其他方法(例如,按用戶習慣進行跟蹤-不可靠;或者.Net方法將序列化會話存儲為HTML,然后將數據從瀏覽器中與每個請求)。 Dmytro和Eric B.都已經解釋了該機制。

服務器端會話期滿(超時后清除會話)有點棘手,因為您必須知道會話何時可能確切到期,以便服務器端會話映射不會增長到無限,也不會消失太快。 (如果沒有由於故障而導致計算機崩潰/斷開連接,並且每個用戶在離開前都單擊注銷,那將是非常不錯的選擇。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM