1. 程式人生 > >Socket編程之Tomcat模擬_采坑匯總

Socket編程之Tomcat模擬_采坑匯總

buffere ava 程序 編程 str add targe .com request

用java.net.Socket來模擬實現Tomcat,碰到了一些坑,大部分是沒有想到的,記錄下來自查。

直接上代碼,

public class TomcatDemo {

    private static ExecutorService executorService = Executors.newCachedThreadPool();

    public static void main(String[] args) throws IOException {
        //監聽9000端口
        @SuppressWarnings("resource")
        ServerSocket serverSocket 
= new ServerSocket(9000); System.out.println("Tomcat服務啟動成功!"); while (!serverSocket.isClosed()) { //阻塞式 Socket request = serverSocket.accept(); System.out.println(request.getInetAddress()); executorService.execute(() -> {
try { InputStream inputStream = request.getInputStream(); System.out.println("收到請求..."); BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); StringBuffer sb = new StringBuffer(); String line;
while((line = br.readLine()) != null) { sb.append(line).append("\r\n"); } System.out.println(sb.toString()); //由servlet處理業務邏輯 System.out.println("-----------------end"); //請求結束... OutputStream outputStream = request.getOutputStream(); outputStream.write("HTTP/1.1 200 OK\r\n".getBytes()); outputStream.write(("Content-Length: " + "Hello World!".getBytes().length + "\r\n\r\n").getBytes()); outputStream.write("Hello World!".getBytes()); outputStream.flush(); System.out.println("請求結束..."); } catch (IOException e) { e.printStackTrace(); } finally { try { request.close(); } catch (Exception e2) { e2.printStackTrace(); } } }); } } }

運行程序,使用Chrome訪問localhost:9000

技術分享圖片

問題有兩個,

(1) 竟然發起兩次GET請求

(2) 出現socket write error

起初開始解決socket write error,大多數說是因為socket提前close或者超時導致的,但是發起的請求還沒有結束。後來一步步調試,發現代碼在 line = br.readLine()) != null 處阻塞等待了!

原來是br.readLine()的機制同自己想的並不一樣,它是阻塞式的,叉掉http://localhost:9000/的請求後,後續代碼才繼續被執行。

技術分享圖片

增加如下判斷代碼解決,

while((line = br.readLine()) != null) {
    if (line.length() == 0){
        break;
    }
    sb.append(line).append("\r\n");
}

但是socket write error的問題還在,這個應該就和重復請求有關系了。

改用Firefox訪問http://localhost:9000/,發現請求正常,

技術分享圖片

看來是Chrome的問題,遂查了下,應該是插件造成的請求重復發送,這也導致了如上socket write error的問題。

用Chrome訪問還會出現請求/favicon.ico,這個是Chrome後臺默默做的,用來顯示和網站相關的信息。這也正是平時大家說的Chrome一次GET請求,出現兩次的根源。

技術分享圖片

Socket編程之Tomcat模擬_采坑匯總