1. 程式人生 > >Java Socket程式設計中處理長連線的方法

Java Socket程式設計中處理長連線的方法

因為實習可能要用Java,所以學習了一下Java,正好計算機網路實驗要寫一個Web伺服器,可以用來練練手。
實現Web伺服器時,最基本的流程就是當有客戶端連線伺服器時,把連線交給一個執行緒,由這個執行緒來處理這個連線。處理的流程也很簡單,就是讀取一個請求,然後返回響應。
我第一步準備實現伺服器讀取完客戶端的請求後,再將這些請求返回給客戶端,用來測試我前期的工作,然後再進行下一步。因為在這一步我沒有想要解析請求,因此我實現的方法是將請求直接以InputStreamReader()的方法按byte進行讀取,讀取完畢後再將讀取的內容寫回Socket。
但是測試的時候發現了問題,瀏覽器訪問伺服器的時候,一直處在等待伺服器響應的狀態。在原始碼中加了幾個print以後發現,執行緒總是阻塞到了讀Socket的位置。這時我意識到了,伺服器讀取了客戶端的請求後,客戶端並沒有關閉這個Socket,因此發生了阻塞。客戶端之所以沒有關閉Socket,是因為現在HTTP預設使用keep-alive連線,也就是長連線,這是用來減輕伺服器負擔的一種方法。
網上一開始找到的方法是給Socket連線使用setSoTimeout()方法設定一個超時值,這樣的話伺服器會主動關閉這個連線,也就是說伺服器只會被阻塞一個有限的時間值。但我覺得這種方法並不好,因為網路狀況不好的時候,你很難保證伺服器在這個時間值內會接收完請求。而且伺服器主動關閉這個連線後,客戶端再次發請求時就要產生一個新的連線,加重了伺服器的負擔。
因此我採用了第二種方法,就是使用BufferedReader。這樣一來,我就不再以byte為單位從Socket中進行讀取了,而是以行為單位從Buffer中進行讀取。這樣的話,當讀取到CRLF,也就是一個空行時,客戶端的一個請求就接收完畢了,就可以開始處理了。