日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat运行原理(一)--- socket通讯

發(fā)布時間:2023/12/31 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat运行原理(一)--- socket通讯 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

說起tomcat首先很容易聯(lián)想到IIS,由此認(rèn)識了IIS,它是一個web容器,天生的多線程,及時響應(yīng)用戶提交的請求返回html頁面,這就是我了解的最初的web容器的功能,由此我們來認(rèn)識tomcat也并不困難,可以的話,在了解完tomcat后我們可以繼續(xù)了解jboss、jetty等,好我們進(jìn)入主題。

  我們在平時開發(fā)的過程中是在使用eclipse時候才啟動tomcat,對于一個web容器而言,簡而言之,它是系統(tǒng)的一個守護(hù)進(jìn)程,守護(hù)著對這臺服務(wù)器某個端口發(fā)起的請求,基于這一點,它就需要一個監(jiān)聽程序,這個監(jiān)聽程序來獲取來自這個端口的特定請求的數(shù)據(jù),ok,直接點講,我們這里使用Socket來獲取某個端口,通常是80端口的http請求,通過簡單的Java

  程序的死循環(huán)(粗糙的做法,后面逐步優(yōu)化)來實現(xiàn)不斷的獲取80端口http請求,來達(dá)到監(jiān)聽80端口http請求的目的。java.net包下面的Socket和ServerSocket兩個類就能實現(xiàn)我們對8080端口的監(jiān)聽,去除中間的邏輯代碼,我們只看這個兩個類的演繹的話如下:

1 ServerSocket serverSocket = new ServerSocket(8080, 1, InetAddress.getByName("10.10.10.106"));

 對本機(jī)的8080端口進(jìn)行監(jiān)聽

1 socket = serverSocket.accept(); 2 input = socket.getInputStream(); 3 output = socket.getOutputStream();

? ?? 以上代碼就是獲取監(jiān)聽結(jié)果。

這是最簡單和最精簡的Socket通訊原理,基于這個核心點我們來開發(fā)一個簡易的,可以提供靜態(tài)頁面訪問的?custom tomcat,準(zhǔn)備一個index.html文件放到/home/webroot目錄下,那么除去拓展上面代碼外,我們還需要一個Response和一個Request。

  類設(shè)計如下:

  HttpServer: 主函數(shù)所在類,負(fù)載啟動ServerSocket和 操作整合Socket監(jiān)聽到的數(shù)據(jù),以及返回結(jié)果,即操作Response和Request。

  Request:?封裝Socket監(jiān)聽到的用戶端請求,包括請求的http uri信息。

  Response: 封裝需要推送到客戶端的結(jié)果數(shù)據(jù),即我們需要根據(jù)http uri?去本機(jī)尋找相應(yīng)的資源,寫給客戶端。

  言簡意賅,進(jìn)入代碼,首先?Request類代碼:

public class Request {private InputStream input;private String uri;public Request(InputStream input) {this.input = input;}public void parse(){StringBuffer request = new StringBuffer(2048);int i;byte[] buffer = new byte[2048];try{ i = input.read(buffer);}catch(IOException e) { e.printStackTrace(); i = -1; }for (int j=0; j<i; j++) {request.append((char) buffer[j]);} System.out.print(request.toString()); uri = parseUri(request.toString());}private String parseUri(String requestString) { int index1, index2; index1 = requestString.indexOf(' ');if (index1 != -1) { index2 = requestString.indexOf(' ', index1 + 1);if (index2 > index1) return requestString.substring(index1 + 1, index2); } return null;}public String getUri() {return uri;}}

代碼解釋:類包括一個屬性和兩個方法,input屬性即是從Socket監(jiān)聽到的信息,Socket會將監(jiān)聽到的信息放入一個InputStream中,我們使用Reqeust類的Input屬性來接受。接收到輸入流后,在parse中對這個輸入流進(jìn)行解析成字符串,即對Http請求進(jìn)行拆解,得到完整的Http URL,所以這個方法是私有的,是類存在意義的核心所在,而提供的對外方法parseUri是負(fù)載將parse解析的url結(jié)果提供給外界,即,客戶端發(fā)來請求那個文件,具體的是最終提供給Response類,Response類得到這個文件名稱后,去本地制定目錄讀取文件。Tomcat中通常就是webapps目錄啦,很熟悉了吧,哈哈。

  Response類如何實現(xiàn)這個讀取文件的歷史使命呢,代碼如下:

public class Response {private static final int BUFFER_SIZE = 1024; Request request; OutputStream output;public Response(OutputStream output) { this.output = output;}public void setRequest(Request request){this.request = request;}public void sendStaticResource() throws IOException{byte[] bytes = new byte[BUFFER_SIZE];FileInputStream fis = null;try {File file = new File(HttpServer.WEB_ROOT, request.getUri());if (file.exists()){ fis = new FileInputStream(file); int ch = fis.read(bytes, 0, BUFFER_SIZE); while (ch!=-1) { output.write(bytes, 0, ch); ch = fis.read(bytes, 0, BUFFER_SIZE);}}else {String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +"Content-Type: text/html\r\n" + "Content-Length: 23\r\n" +"\r\n" +"<h1>File Not Found</h1>";output.write(errorMessage.getBytes());}}catch(Exception e) {System.out.println(e.toString());}finally{fis.close();}}}

? ? ? ? 代碼解釋:Response一共三個屬性,一個方法。三個屬性,一個是設(shè)置屬性,BUFFER_SIZE設(shè)置讀寫字節(jié)流大小,關(guān)于讀寫文件,我個人覺得和服務(wù)器的性能和程序性能息息相關(guān),不宜設(shè)定過大或過小(此處有不同見解的同仁歡迎來噴,我對這塊理解目前限于此)。Reqeust屬性,對照前文呼應(yīng),Response需要獲取Request類的uri結(jié)果信息,所以這里放了一個Request屬性,獲取uri。Output,就不用說了,也是這個類存在的核心意義,依照Request類提供的uri信息,在本地讀寫文件后,形成一個輸出來,存放到output中,那么這項工作就由sendStaticResource這個共有方法完成啦。?

? ? ? ? 好,代碼到這個,可以說我們大家已經(jīng)看到一個tomcat模型了,有點萬事俱備,只欠東風(fēng)的感覺,客戶端發(fā)起請求,Response和Reqeust有了,那么繼續(xù)往上游考慮,Reqeust依賴于客戶端的請求,自然以來于Socket數(shù)據(jù)。我們在這里做得簡便一點,將ServerSocket和Socket封裝到一個HttpServer類中來,代碼如下:

public class HttpServer {public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";private boolean shutdown = false;public static void main(String[] args){HttpServer httpServer = new HttpServer();httpServer.await();}public void await(){ServerSocket serverSocket = null;Integer port = 8080; try { serverSocket = new ServerSocket(port, 1, InetAddress.getByName("10.10.10.106")); } catch(IOException e) { e.printStackTrace(); System.exit(1); } while(!shutdown){Socket socket = null;InputStream input = null;OutputStream output = null;try { socket = serverSocket.accept();input = socket.getInputStream(); output = socket.getOutputStream(); Request request = new Request(input); request.parse(); Response response = new Response(output);response.setRequest(request); response.sendStaticResource(); socket.close(); shutdown = request.getUri().equals(SHUTDOWN_COMMAND);}catch(Exception e) {e.printStackTrace();continue;}}}}

? ? ? 代碼解釋:我們知道啟動tomcat之后,只要服務(wù)正常,客戶端任意時候發(fā)起一個http請求,tomcat就會響應(yīng),那么這里我們肯定需要一個while循環(huán)來模擬不間斷的監(jiān)聽,類await方法就是負(fù)責(zé)不斷的獲取socket監(jiān)聽到的結(jié)果,有立刻調(diào)動Reqeust和Response進(jìn)行響應(yīng),加入主函數(shù),為的是我們這個是模擬的控制臺程序,需要一個程序入口,main函數(shù)就是程序入口。此外,HttpServer類包括一個靜態(tài)屬性SHUTDOWN_COMMAND,輸入為true則停止這個main函數(shù),變量初始值為false,當(dāng)客戶端也就是Request響應(yīng)得到客戶端輸入?http://10.10.10.108:8080/SHUTDOWN時候,則變量在while中會置成true,緊接著停止main,結(jié)束應(yīng)用程序進(jìn)程。

 在eclipse中或者在命令行中啟動這個main函數(shù),命令行則是輸入?java HttpServer.java。eclipse則是在main函數(shù)中右鍵?run as application啟動。我們打開瀏覽器,輸入?http://10.10.10.108:8080/index.html,回車結(jié)果如下

  

 

?

總結(jié)

以上是生活随笔為你收集整理的Tomcat运行原理(一)--- socket通讯的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。