2011-11-09 59 views
3

我已經構建了一個簡單的Java程序,可以在本地作爲服務器使用。保持來自自制Java服務器的持續連接

在它做了一些事情,比如預覽目錄的那一刻,轉發到index.html的,如果目錄中包含它,發送Last-Modified頭和正確地響應客戶端的請求If-Modifed-Since

我現在需要做的是讓我的程序接受持久連接。它目前是線程化的,這樣每個連接都有自己的線程。我想把我的整個線程代碼放在一個循環中,直到Connection: close或指定的超時。

有沒有人有任何想法從哪裏開始?

編輯:這是一個大學項目,必須在沒有使用框架的情況下完成。

我有一個無限循環的主要方法,每次循環它創建一個Socket對象,然後創建一個HTTPThread對象(我自己創建的一個類) - 處理單個請求。

我想允許多個請求在單個連接內使用Connection: keep-alive請求標頭進行工作。我期望在我的HTTPThread類中使用循環,我只是不確定如何傳遞多個請求。

感謝提前:)

+0

你能再解釋一下,當你說「持續連接」時,你的意思是什麼?如果會話臨時斷開連接,您是否可以保存會話狀態以恢復會話狀態? – AlexR

+0

我的問題是我不完全明白我需要做什麼!目前我有一個循環調用一個名爲HTTPThread的類。它傳遞一個inputStream和一個outputStream。 HTTPThread類然後相應地解析請求。如果連接狀態是保持活動狀態,我想以某種方式使用我已經有的下一個請求的連接。 – Alex

回答

1

我假設你正在實施的HTTP協議的代碼自己開始與Socket API的應用。而且你正在實現HTTP規範的持久連接部分。

您可以按照您的建議將代碼放入循環中,然後使用Socket.setSoTimeout設置阻塞操作的超時時間,從而設置HTTP超時時間。除了不關閉它們之外,您不需要爲連接重新使用流而做任何事情。


我會指出有更簡單的方法來實現Web服務器。有許多現有的Java Web服務器框架和應用程序服務器,或者您可以重新使用Apache HTTP協議棧。

+0

我有一個循環當前爲每個請求聲明一個套接字。一個HTTPThread對象(我的所有代碼都在這裏)接受一個輸入流和一個輸出流,並在那裏處理單個請求。我怎麼能從HTTPThread類中執行多個請求 - 單個連接? – Alex

+0

soTimeout與持續連接有什麼關係? – Kevin

+0

如此處所述,http://en.wikipedia.org/wiki/HTTP_persistent_connection,HTTP 1.1始終使用持久連接,除非標頭中另有說明。 Apache 2.2在閒置5秒後關閉套接字。所以你必須不關閉套接字,而且還要設置一些定時器來關閉它,如果它閒置太久的話。做到這一點的一種方法是有一個專門的管理線程來處理這個(也許是其他的)任務。 – Kevin

0
  1. 如果它應該像一個Web服務:從客戶端打開2個插槽,一個用於請求,一個用於 響應。保持插座和流路暢通無阻。

    您需要定義一個分隔符來通知對方一個 傳輸結束。二進制的特殊位字符串,用於基於文本的協議(如XML)的特殊 字符(通常是換行符)。

  2. 如果您確實嘗試實施自己的http服務器,則應該使用已實施HTTP 1.1連接保持標準的library
+0

它的功課我懷疑正確的解決方案是使用已經做到這一點的圖書館。 – Kevin

+0

我明白了,那麼你當然應該自己實現它。 ;)Java Socket API提供了一種設置SO_KEEPALIVE的方法:http://download.oracle.com/javase/6/docs/api/java/net/Socket.html#setKeepAlive(boolean) – Stephan

+0

我認爲保持活力一個套接字不同於HTTP 1.1持久連接。 – Kevin

0

一些想法,讓你開始:

此Wikipedia文章介紹了HTTP 1。1個持久連接:

http://en.wikipedia.org/wiki/HTTP_persistent_connection

你想不關閉套接字,但一些不活躍一段時間後(Apache 2.2的使用5秒)要關閉它。

你有兩種方法來實現:

  1. 在你的線程不關閉套接字,不退出線程,而是把一個讀超時插座上(無論你想支持)。當你調用讀取它會阻塞,如果超時過期,那麼你關閉套接字,否則你讀下一個請求。這樣做的缺點是每個持久連接都可以保持一個線程和一個套接字,無論你的最大等待時間是多少。這意味着您的解決方案無法擴展,因爲您持有太久的線程(但對於學校項目而言可能沒問題)!

  2. 通過維護一個元組列表({socket,timestamp},擁有一個後臺線程監視器並關閉超時連接並使用NIO在現有的open上檢測一個新讀取來解決(1)插座。因此,在完成讀取初始請求之後,您只需退出該線程(將其返回到線程池)。顯然這更復雜,但它具有釋放請求線程的好處。

+0

請原諒我的無知,但你如何閱讀下一個請求..我認爲這就是我被卡住的地方。另外,在任何時候,我都不會調用關閉套接字的方法,關閉輸入和輸出流,是否也會做同樣的事情? – Alex

+0

在哪種情況下您有興趣?在第一種情況下,您將讀入輸入流並阻塞,直到客戶端發送另一個請求,或發生超時,或者客戶端強制關閉連接。在第二種情況下,您對非阻塞IO apis執行相同的操作,這意味着讀取會立即返回,但是當流中有新數據可用時,您可以從某個選擇循環中找到該循環,該循環運行在不同的線程中。 – Kevin

+0

如果關閉套接字,它也會關閉輸入和輸出流。 – Kevin