1. 程式人生 > >尋找Tomcat與Socket關係的過程

尋找Tomcat與Socket關係的過程

在寫一個socket程式設計的測試類的時候,發散了一下思維,想到這個Socket程式設計有什麼用?在實際的應用中都使用Tomcat作為伺服器,Tomcat支援的請求協議是HTTP協議,跟Socket有什麼關係?Tomcat中究竟有沒有使用Socket程式設計?是如何使用的?瀏覽器能夠new出一個Socket傳送給伺服器嗎?瀏覽器每次向伺服器請求都會遵照TCP/IP協議的三次握手嗎?

找了一些帖子,找出對回答以上問題有幫助的梳理了一下

一、Java網路程式設計之TCP通訊

1.概念概述

Socket類是Java執行客戶端TCP操作的基礎類,這個類本身使用程式碼通過主機作業系統的本地TCP棧進行通訊。Socket類的方法會建立和銷燬連線,設定各種Socket選項
ServerSocket類是Java執行服務端TCP操作的基礎類,該類執行與伺服器,監聽入站的TCP連線,每個socket伺服器監聽伺服器的某個埠,當遠端主機的客戶端嘗試連線到此埠時,伺服器被喚醒,並返回一個表示兩臺主機之間socket的Socket物件。

TCP是一種面向連線,可靠的、基於位元組流的傳輸層通訊協議。TCP通訊分為客戶端和伺服器端,對應的物件分別是Socket和ServerSocket。
當一臺計算機需要與另一臺計算機連線時,TCP協議會讓它們建立一個連線:用於傳送和接受資料的虛擬鏈路。TCP協議負責收集資訊包,並將其按照適當的次序放好傳送,當接收端收到後再將其正確的還原。為了保證資料包再傳送中準確無誤,TCP使用了重發機制:當一個通訊實體傳送一個訊息給另一個通訊實體後需要收到另一個實體的確認訊息,如果沒有收到訊息,則會再次重發剛才傳送的訊息。

2.TCP通訊

Socket類實現客戶端套接字
Socket s=new Socket(“127.0.0.1”, 10001);//建立一個流套接字並將其連線到指定主機上的指定埠號
ServerSocket類實現伺服器套接字
ServerSocket ss=new ServerSocket(10001);//建立繫結到特定埠的伺服器套接字

3.Socket在瀏覽上的應用

在Eclipse中編寫伺服器端,然後利用瀏覽器進行訪問。

public class SocketServer
{
    public static void main(String[] args) throws IOException 
    {
        ServerSocket server=new ServerSocket(11000);
        Socket client=server.accept();
        PrintWriter out=new PrintWriter(client.getOutputStream(),true);
        BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
        String line=null;
        while((line=in.readLine())!=null)
            System.out.println(line);
        out.println("你好!");
        server.close();
    }
}

GET / HTTP/1.1
Host: 10.38.48.195:11000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3357.400 QQBrowser/9.6.11858.400
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cache-Control: max-age=0
Proxy-Connection: keep-alive
Upgrade-Insecure-Requests: 1
X-Lantern-Version: 3.7.4

二、Java基於socket服務實現UDP協議的方法

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPServer02 {
public static void main(String[] args) throws IOException{ 
  System.out.println("接收端啟動…………"); 
 /* 
  2、建立UDP的socket的服務,必須明確一個埠號 
  3、建立資料包,用於儲存接收到的資料,方便用資料包物件的方法解析這些資料 
  4、使用DatagramSocket的receive方法將接收到的資料儲存到資料包中 
  5、通過資料包的方法解析資料包中的資料 
  5、關閉socket服務 
  */
  //udpsocket服務,使用DatagramSocket物件 
  DatagramSocket ds=new DatagramSocket(10003); 
  while(true){ 
   //使用DatagramPacket將資料封裝到該物件中 
   byte[] buf=new byte[1024]; 
   DatagramPacket dp=new DatagramPacket(buf, buf.length); 
   //通過udp的socket服務將資料包傳送出去,通過send方法 
   ds.receive(dp);//阻塞式的。 
   //通過資料包的方法解析資料包中的資料,比如,地址、埠、資料內容等 
   String ip=dp.getAddress().getHostAddress(); 
   //String name=dp.getAddress().getHostName(); 
   int port=dp.getPort(); 
   String text=new String(dp.getData(),0,dp.getLength()); 
   //System.out.println("-----"+ip+"-----"+name+"-----"+port+"-----"+text); 
   System.out.println("-----"+ip+"----------"+port+"-----"+text); 
  } 
  //關閉資源 
  //ds.close(); 
 } 
}


package com.maven.test.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPClient02 {
public static void main(String[] args) throws IOException{ 
  System.out.println("傳送端啟動…………"); 
 /* 
  * 1、建立udp傳輸的傳送端 
  2、建立UDP的socket的服務 
  3、將要傳送的資料封裝到資料包中 
  4、通過udp的socket服務將資料包傳送出去 
  5、關閉socket服務 
  */
  //udpsocket服務,使用DatagramSocket物件 
  DatagramSocket ds=new DatagramSocket(9999);//監聽埠 
  //將要傳送的資料封裝到資料包中 
  //String str="udp傳輸演示,go"; 
  BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));//鍵盤輸入 
  String line=null; 
  //使用DatagramPacket將資料封裝到該物件中 
  while((line=bufr.readLine())!=null){ 
   byte[] buf=line.getBytes();// 
   DatagramPacket dp= 
     new DatagramPacket(buf, buf.length,InetAddress.getByName("127.0.0.1"),10003); 
   //通過udp的socket服務將資料包傳送出去,通過send方法 
   ds.send(dp); 
   if("886".equals(line)){ 
    break; 
   } 
  } 
  //關閉資源 
  ds.close(); 
 } 
}

三、Socket與Servlet的簡單理解

http://blog.csdn.net/sdjkjsdh/article/details/51569481
Servlet是Socket的一種應用,在每次請求時,會產生三次握手
1、 Socket:使用TCP/IP或者UDP協議在伺服器與客戶端之間進行傳輸的技術,是網路程式設計的基礎
Servlet:使用http協議在伺服器與客戶端之間通訊的技術。是Socket的一種應用。

2、 tcp/ip協議:關注的是客戶端與伺服器之間的資料傳輸是否成功(三次握手,傳輸失敗會重發)
http協議:是在tcp/ip協議之上進一步封裝的一層協議,關注的事資料傳輸的格式是否規範,底層的資料傳輸還是運用了socket和tcp/ip

四、Tomcat中使用Socket程式設計

在tomcat中找到了具體的處理Socket的Process類,確定了Tomcat的底層是Socket程式設計

org.apache.coyote.http11.Http11Processor.process(Socket)
      public void process(Socket theSocket)
            throws IOException {
            RequestInfo rp = request.getRequestProcessor();
            rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
            // Set the remote address
            remoteAddr = null;
            remoteHost = null;
            localAddr = null;
            localName = null;
            remotePort = -1;
            localPort = -1;

  // Setting up the I/O
   this.socket = theSocket;
   inputBuffer.setInputStream(socket.getInputStream());
   outputBuffer.setOutputStream(socket.getOutputStream());

   // Error flag
   error = false;
   keepAlive = true;

   int keepAliveLeft = maxKeepAliveRequests;
   int soTimeout = endpoint.getSoTimeout();

   // When using an executor, these values may return non-positive values
   int curThreads = endpoint.getCurrentThreadsBusy();
   int maxThreads = endpoint.getMaxThreads();
   if (curThreads > 0 && maxThreads > 0) {
       // Only auto-disable keep-alive if the current thread usage % can be
       // calculated correctly
       if ((curThreads*100)/maxThreads > 75) {
           keepAliveLeft = 1;
       }
   }

   try {
       socket.setSoTimeout(soTimeout);
   } catch (Throwable t) {
       log.debug(sm.getString("http11processor.socket.timeout"), t);
       error = true;
   }

   boolean keptAlive = false;

   while (started && !error && keepAlive && !endpoint.isPaused()) {

       // Parsing the request header
       try {
           if (keptAlive) {
               if (keepAliveTimeout > 0) {
                   socket.setSoTimeout(keepAliveTimeout);
               }
               else if (soTimeout > 0) {
                   socket.setSoTimeout(soTimeout);
               }
           }
           inputBuffer.parseRequestLine();
           request.setStartTime(System.currentTimeMillis());
           keptAlive = true;
           if (disableUploadTimeout) {
               socket.setSoTimeout(soTimeout);
           } else {
               socket.setSoTimeout(timeout);
           }
           // Set this every time in case limit has been changed via JMX
           request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
           inputBuffer.parseHeaders();
       } catch (IOException e) {
           error = true;
           break;
       } catch (Throwable t) {
           if (log.isDebugEnabled()) {
               log.debug(sm.getString("http11processor.header.parse"), t);
           }
           // 400 - Bad Request
           response.setStatus(400);
           adapter.log(request, response, 0);
           error = true;
       }

       if (!error) {
           // Setting up filters, and parse some request headers
           rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
           try {
               prepareRequest();
           } catch (Throwable t) {
               if (log.isDebugEnabled()) {
                   log.debug(sm.getString("http11processor.request.prepare"), t);
               }
               // 400 - Internal Server Error
               response.setStatus(400);
               adapter.log(request, response, 0);
               error = true;
           }
       }

       if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
           keepAlive = false;

       // Process the request in the adapter
       if (!error) {
           try {
               rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
               adapter.service(request, response);
               // Handle when the response was committed before a serious
               // error occurred.  Throwing a ServletException should both
               // set the status to 500 and set the errorException.
               // If we fail here, then the response is likely already
               // committed, so we can't try and set headers.
               if(keepAlive && !error) { // Avoid checking twice.
                   error = response.getErrorException() != null ||
                           statusDropsConnection(response.getStatus());
               }

           } catch (InterruptedIOException e) {
               error = true;
           } catch (Throwable t) {
               log.error(sm.getString("http11processor.request.process"), t);
               // 500 - Internal Server Error
               response.setStatus(500);
               adapter.log(request, response, 0);
               error = true;
           }
       }

       // Finish the handling of the request
       try {
           rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
           // If we know we are closing the connection, don't drain input.
           // This way uploading a 100GB file doesn't tie up the thread 
           // if the servlet has rejected it.
           if(error)
               inputBuffer.setSwallowInput(false);
           inputBuffer.endRequest();
       } catch (IOException e) {
           error = true;
       } catch (Throwable t) {
           log.error(sm.getString("http11processor.request.finish"), t);
           // 500 - Internal Server Error
           response.setStatus(500);
           // No access logging since after service method 
           error = true;
       }
       try {
           rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
           outputBuffer.endRequest();
       } catch (IOException e) {
           error = true;
       } catch (Throwable t) {
           log.error(sm.getString("http11processor.response.finish"), t);
           error = true;
       }

       // If there was an error, make sure the request is counted as
       // and error, and update the statistics counter
       if (error) {
           response.setStatus(500);
       }
       request.updateCounters();

       rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);

       // Don't reset the param - we'll see it as ended. Next request
       // will reset it
       // thrA.setParam(null);
       // Next request
       inputBuffer.nextRequest();
       outputBuffer.nextRequest();

   }

   rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);

   // Recycle
   inputBuffer.recycle();
   outputBuffer.recycle();
   this.socket = null;
   // Recycle ssl info
   sslSupport = null;
}

相關推薦

尋找TomcatSocket關係過程

在寫一個socket程式設計的測試類的時候,發散了一下思維,想到這個Socket程式設計有什麼用?在實際的應用中都使用Tomcat作為伺服器,Tomcat支援的請求協議是HTTP協議,跟Socket有什麼關係?Tomcat中究竟有沒有使用Socket程式設計?是

TomCatJvm關係

1,JVM(虛擬機器),相當於電腦安裝系統一樣,可以執行應用程式。讓tomcat跑起來,就得有jdk,而jdk自帶了JVM,安裝完了jdk,把安裝jkd的bin目錄告訴tomca,就可以了。 2,有的web伺服器不必安裝jdk,因為自帶了,如weblogic。 3,tomc

tomcat jvm關係

現象: 一個tomcat可以有多個web應用,當它啟動時,會啟動一個jvm程序。多個tomcat,會啟動多個jvm程序。 原因: Tomcat是一個JSP/Servlet容器。其作為Servlet容器,有三種工作模式:獨立的Servlet容器

servlet tomcat 之間的關係

雖然它的靈活配置和支援技術的互操作性使Apache Tomcat在許多情況下充當Web應用伺服器,但Tomcat主要是Java Servlet容器。 利用Java Servlet和JSP API的實現,Tomcat能夠接收來自客戶端的請求,動態編譯一個容器管理的Java類來處理相關應用程式上下文

Java Servlet 實戰入門教程-00-Servlet 系列教程彙總 Servlet 是什麼,Servlettomcat/j2EE的關係

系列文章彙總 寫作緣由 原來學習過多次 servlet,但是平時工作中一直使用 spring mvc 等框架。使用的時候寫幾個註解,實際原理並不知曉。 此係列文章,意在知其然,知其所以然。 學習之路,就是保持一顆好奇之心。 Servlet 概念 servlet是

Tomcat-connector的微調(3): processorCachesocket.processorCache

tomcat在處理每個連線時,Acceptor角色負責將socket上下文封裝為一個任務SocketProcessor然後提交給執行緒池處理。在BIO和APR模式下,每次有新請求時,會建立一個新的SocketProcessor例項(在之前的tomcat對keep-alive的實現邏輯裡也介紹過

WebSocketSocket、TCP、HTTP的關係和異同點

今天來講一下與其他協議的區別和相同點,讓各位同學能夠更加深入的去了解和運用各種協議。 1 什麼是WebSocket?   WebSocket從滿足基於Web的日益增長的實時通訊需求應運而生,解決了客戶端發起多個Http請求到伺服器資源瀏覽器必須要在經過長時間的輪詢問題,實

TCPSOCKET的三次握手的對應關係

TCP/IP 要想理解socket首先得熟悉一下TCP/IP協議族,TCP/IP(Transmission Control Protocol/Internet Protocol)即傳輸控制協議/網間協議,定義了主機如何連入因特網及資料如何再它們之間傳輸的標準, 從字面意

tomcatjvm的關係分析

首先,我們來看幾個概念: 1.什麼是jvm 我們從作業系統的層面來理解,jvm其實就是作業系統中的一個程序。既然是一個程序,那麼我們很容易的可以通過工作管理員來檢視。假設此時我們啟動myeclipse(myeclipse其實就是用java語言編寫的一個軟體,他的執行必然會啟

ApacheTomcat有什麼關係和區別

經常在用apache和tomcat等這些伺服器,可是總感覺還是不清楚他們之間有什麼關係,在用tomcat的時候總出現apache,總感到迷惑,到底誰是主誰是次,因此特意在網上查詢了一些這方面的資料,總結了一下:   一  apache支援靜態頁,tomcat支援動態的,比如servlet等,   一般使用a

HIVEmysql的關係 hive常用命令整理 hivehdfs整合過程

轉:https://my.oschina.net/winHerson/blog/190131 二、hive常用命令 1. 開啟行轉列功能之後: set hive.cli.print.header=true; // 列印列名 set hive.cli.print.row.to.vertical=true; /

tomcat java web中url路徑的配置以及使用規則詳情(長期更新)

root 每一個 ava 目錄 clip ima 文件夾 logs 需要 首先我們看一下在myeclipse中建立的java web項目的結構 在這裏我們需要註意這個webroot也就是我們在tomcat裏的webapp裏面的應用 之所以每一個項目都有這個webroot

Abp(.NetCore)開發發布過程2

for 默認 而是 type list csr 背景 size 請求 在Abp(.NetCore)開發過程中遇到很多問題,今天記錄下Abp的防CSRF功能(AntiForgeryToken ), 背景知識。 AntiForgeryToken 可以說是處理/預防CSRF的一

PL/SQL學習筆記_03_存儲函數存儲過程

employ span function aps 學習 lsi acl 操作 img ORACLE 提供可以把 PL/SQL 程序存儲在數據庫中,並可以在任何地方來運行它。這樣就叫存儲過程或函數。 存儲函數:有返回值,創建完成後,通過select function() f

ceph學習筆記之五 Pool映射過程

ceph sds Pool Pool是一個抽象的存儲池,它規定了數據冗余的類型以及對應的副本分布策略。目前實現了兩種Pool類型:Replicated類型和Erasure Code類型。一個Pool由多個PG構成。對象映射過程 對象映射過程指的是查找對象在集群中分布的位置信息,其過程分為兩步:A、

Oracle數據類型,函數存儲過程

unicode 普通 覆蓋 表達式 必須 all 浮點數 pro int 字符串類型 固定長度:char nchar n 表示Unicode編碼 可變長度: varchar2 nvarchar2 數字類型:number(P,S)P:整數位

MySQL入門第三天——函數存儲過程

logs mysql入門 .com mage http size strong 分享 png 一、函數         MySQL入門第三天——函數與存儲過程

Tomcat安裝和配置過程

修改 除了 環境變量 文件 結構 apache 總結 1.8 必須 tomcat的下載、配置、啟動方法。網上教程亂七八糟,還是自己mark一下備用吧。 一、官網下載Tomcat的壓縮包 Tomcat是Apache軟件基金會的一個開源項目。登錄Apache官網即可找到下載的界

二級制包安裝Tomcat RPM包安裝Tomcat

class mirror 包安裝 系統 -o server var dev ase 1:下載二級制包 wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-8/v8.0.47/bin/apache-tomcat-8.0.47.

tomcat nginx,apache的區別是什麽?

訪問服務器 代理 edit 資源分離 訪問 nor pac img 衍生 == tomcat 與 nginx,apache的區別是什麽? - 知乎https://www.zhihu.com/question/32212996 Apache HTTP Server