Socket編程之Tomcat模擬_采坑匯總
阿新 • • 發佈:2019-05-13
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模擬_采坑匯總