国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

試解析Tomcat運(yùn)行原理(一)--- socket通訊

2019-11-14 22:33:23
字體:
供稿:網(wǎng)友
試解析Tomcat運(yùn)行原理(一)--- socket通訊

  關(guān)于這篇文章也確實(shí)籌劃了很久,今天決定開篇寫第一篇,說起tomcat首先很容易聯(lián)想到IIS,因?yàn)槲易铋_始使用的就是.net技術(shù),我第一次使用asp寫學(xué)生成績(jī)管理系統(tǒng)后,很茫然如何讓別人都能看到或者說使用這個(gè)系統(tǒng)呢?由此認(rèn)識(shí)了IIS,它是一個(gè)web容器,天生的多線程,及時(shí)響應(yīng)用戶提交的請(qǐng)求返回html頁面,這就是我了解的最初的web容器的功能,由此我們來認(rèn)識(shí)tomcat也并不困難,可以的話,在了解完tomcat后我們可以繼續(xù)了解jboss、jetty等,好我們進(jìn)入主題。

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

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

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

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

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

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

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

  類設(shè)計(jì)如下:

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

  Request:封裝Socket監(jiān)聽到的用戶端請(qǐng)求,包括請(qǐng)求的httpuri信息。

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

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

 1 public class Request  2 { 3     PRivate InputStream input; 4     private String uri; 5      6     public Request(InputStream input) { 7         this.input = input; 8     } 9     10     public void parse()11     {12         StringBuffer request = new StringBuffer(2048);13         int i;14         byte[] buffer = new byte[2048];15         try16         { 17              i = input.read(buffer);18         }19         catch(IOException e) 20         { 21              e.printStackTrace(); 22              i = -1; 23         }24 25         for (int j=0; j<i; j++) 26         {27             request.append((char) buffer[j]);28         } 29         System.out.print(request.toString()); 30         uri = parseUri(request.toString());31     }32     33     private String parseUri(String requestString) 34     {  35         int index1, index2; 36         index1 = requestString.indexOf(' ');37         if (index1 != -1) { 38             index2 = requestString.indexOf(' ', index1 + 1);39             if (index2 > index1) 40                 return requestString.substring(index1 + 1, index2); 41             }  42         return null;43     }44     45     public String getUri() 46     {47         return uri;48     }49 }

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

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

 1 public class Response { 2  3     private static final int BUFFER_SIZE = 1024;  4     Request request;  5     OutputStream output; 6      7     public Response(OutputStream output)  8     {  9         this.output = output;10     }11 12     public void setRequest(Request request)13     {14         this.request = request;15     }16 17     public void sendStaticResource() throws IOException18     {19         byte[] bytes = new byte[BUFFER_SIZE];20         FileInputStream fis = null;21         try 22         {23                 File file = new File(HttpServer.WEB_ROOT, request.getUri());24                 if (file.exists())25                 { 26                         fis = new FileInputStream(file); 27                         int ch = fis.read(bytes, 0, BUFFER_SIZE); 28                         while (ch!=-1) { 29                             output.write(bytes, 0, ch); 30                             ch = fis.read(bytes, 0, BUFFER_SIZE);31                         }32                 }33                 else 34                 {35                     String errorMessage = "HTTP/1.1 404 File Not Found/r/n" +36                         "Content-Type: text/html/r/n" + 37                         "Content-Length: 23/r/n" +38                         "/r/n" +39                         "<h1>File Not Found</h1>";40                     output.write(errorMessage.getBytes());41                 }42         }43         catch(Exception e) 44         {45                 System.out.println(e.toString());46         }47         finally{48             fis.close();49         }50  51     }52 }

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

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

 1 public class HttpServer { 2      3     public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot"; 4     private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; 5     private boolean shutdown = false; 6     public static void main(String[] args) 7     { 8         HttpServer httpServer = new HttpServer(); 9         httpServer.await();10     }11             12     public void await()13     {14         ServerSocket serverSocket = null;15         Integer port = 8080; 16         try 17         { 18             serverSocket =  new ServerSocket(port, 1, InetAddress.getByName("10.10.10.106")); 19         } 20         catch(IOException e)     21         { 22             e.printStackTrace(); 23             System.exit(1); 24         } 25         26         while(!shutdown)27         {28             Socket socket = null;29             InputStream input = null;30             OutputStream output = null;31             try 32             { 33                 socket = serverSocket.accept();34                  35                 input = socket.getInputStream(); 36                 output = socket.getOutputStream(); 37                 Request request = new Request(input); 38                 request.parse(); 39                 Response response = new Response(output);40                 response.setRequest(request); response.sendStaticResource();  socket.close(); 41                 shutdown = request.getUri().equals(SHUTDOWN_COMMAND);42             }43             catch(Exception e) 44             {45                 e.printStackTrace();continue;46             }47         }48     }49 }

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

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

  本地文件:

  

  好了,夜深啦,就此擱筆了,拋磚引玉,歡迎提議和討論,這個(gè)系列會(huì)繼續(xù)下去,直到一個(gè)完整的可以響應(yīng)一個(gè)java action請(qǐng)求的custom tomcat產(chǎn)品出來。

  最后附上我的源代碼:http://files.VEVb.com/aspnetdream/Project.zip

  參考:《How tomcat works》作者:Budi Kurniawan & Paul Deck


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 句容市| 清徐县| 毕节市| 阿勒泰市| 龙山县| 广饶县| 永和县| 惠东县| 淮阳县| 望城县| 秦皇岛市| 咸宁市| 苍溪县| 南宁市| 晋州市| 谷城县| 四川省| 邛崃市| 浦城县| 安庆市| 玉环县| 宜良县| 绥阳县| 惠州市| 托克逊县| 陆川县| 抚宁县| 大邑县| 永清县| 金阳县| 兰坪| 霍林郭勒市| 施秉县| 佛坪县| 石景山区| 松原市| 施秉县| 嘉荫县| 九龙城区| 长白| 舞阳县|