Android技能樹 — 網路小結(4)之socket/websocket/webservice

青蛙要fly發表於2019-03-03

前言

介於自己的網路方面知識爛的一塌糊塗,所以準備寫相關網路的文章,但是考慮全部寫在一篇太長了,所以分開寫,希望大家能仔細看,最好可以指出我的錯誤,讓我也能糾正。

1.講解相關的整個網路體系結構:

Android技能樹 — 網路小結(1)之網路體系結構

2.講解相關網路的重要知識點,比如很多人都聽過相關網路方面的名詞,但是僅限於聽過而已,什麼tcp ,udp ,socket ,websocket, http ,https ,然後webservice是啥,跟websocket很像,socket和websocket啥關係長的也很像,session,token,cookie又是啥。

Android技能樹 — 網路小結(2)之TCP/UDP

Android技能樹 — 網路小結(3)之HTTP/HTTPS

Android技能樹 — 網路小結(4)之socket/websocket/webservice

相關網路知識點小結- cookie/session/token(待寫)

3.相關的第三方框架的原始碼解析,畢竟現在面試個大點的公司,okhttp和retrofit原始碼是必問的。

Android技能樹 — 網路小結(6)之 OkHttp超超超超超超超詳細解析

Android技能樹 — 網路小結(7)之 Retrofit原始碼詳細解析


正文

1. Socket

我們在網路體系結構小結中提過,TCP/IP的體系結構圖為

Android技能樹 — 網路小結(4)之socket/websocket/webservice

在傳輸層中為TCP和UDP,解決了資料之間的運輸,但是我們很少直接去呼叫TCP和UDP,比如我們現在是要用TCP傳輸資料,你要寫程式碼去進行TCP的三次握手連線和四次揮手斷開等,而且可能還要考慮什麼滑動視窗,累積確認、分組快取、流量控制等?所以我們正需要某個類,這個類幫我們封裝好了TCP的連線,傳輸,斷開等一系列相關各類操作,是不是就很方便了。沒錯,這個類就是Socket。

Android技能樹 — 網路小結(4)之socket/websocket/webservice

Socket 即套接字,是應用層 與 TCP/IP 協議族通訊的中間軟體抽象層,表現為一個封裝了 TCP / IP協議族 的程式設計介面(API)

1.Socket不是一種協議,而是一個程式設計呼叫介面(API),屬於傳輸層(主要解決資料如何在網路中傳輸)
2.即:通過Socket,我們才能在Andorid平臺上通過 TCP/IP協議進行開發
3.對使用者來說,只需呼叫Socket去組織資料,以符合指定的協議,即可通訊

關於Socket的使用,程式碼一搜一大把,這裡我就快速通過,直接講一下大致程式碼流程,我們知道現在是為了把一個資訊從一臺裝置到另外一臺裝置,在網路體系結構小結中提過IP是用來確定資訊最後到哪個目標裝置,所以我們一定要知道IP,到了目標裝置後,目標裝置可能開啟了很多應用程式(多個程式),這時候怎麼知道這個資料包到哪個程式呢,這裡也會涉及到埠,我們平常寫程式碼,有時候是不是會說某個埠被佔用了。所以我們同時除了ip還要知道

所以初步是裝置A的ip裝置A的埠,裝置B的ip,裝置B的埠,換成我們平常的通俗說法就是客戶端ip客戶端埠,服務端ip,服務端埠,外加上我們的Socket用來操作TCP,同時也可以操作 UDP,所以同時還有一個協議。所以最終涉及到這5個元素,socket 通過這5個元素來確定。

Android技能樹 — 網路小結(4)之socket/websocket/webservice

具體的Socket程式碼就不多說了:

客戶端:

public class ClientSocket {
 public static void main(String args[]) {
    String host = "127.0.0.1";
    int port = 8919;
    try {
     Socket client = new Socket(host, port);
     Writer writer = new OutputStreamWriter(client.getOutputStream());
     writer.write("Hello From Client");
     writer.flush();
     writer.close();
     client.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
  }
 
}
複製程式碼

服務端:

public class Server {
  public static void main(String args[]) {
  
    ServerSocket echoServer = null;
    String line;
    DataInputStream is;
    PrintStream os;
    Socket clientSocket = null;
    
    try {
      echoServer = new ServerSocket(9999);
    }
    catch (IOException e) {
      System.out.println(e);
    }
   
    try {
        clientSocket = echoServer.accept();
        is = new DataInputStream(clientSocket.getInputStream());
        os = new PrintStream(clientSocket.getOutputStream());
        // As long as we receive data, echo that data back to the client.
        while (true) {
         line = is.readLine();
         os.println(line);
        }
    } catch (IOException e) {
        System.out.println(e);
      }
    }
}
複製程式碼

看了程式碼,我們發現Socket的一個很大的特點就是服務端和客戶端可以相互傳資料。這和我們平時的網路互動差別挺大的,畢竟我們平常訪問後臺介面,很少說後臺突然通過這個介面發個資料給客戶端是吧,一般都是客戶端主動傳送介面請求,然後才能拿到相關資料。


2. WebSocket

我們在上面的Socket的相關介紹可以看到,Socket是在運輸層做了一層抽象層,是TCP/UDP 的 api工具類,所以Socket不算是應用層類,而我們在相關網路知識點小結- http/https提過Http/Https是屬於應用層的,而我們的WebSocket也是屬於應用層的。所以說WebSocket和Http/Https是同一層級的。

Android技能樹 — 網路小結(4)之socket/websocket/webservice

而我們也經常看到很多所謂的Http與WebSocket的區別文章等,比如:

Android技能樹 — 網路小結(4)之socket/websocket/webservice

而我們在上面介紹Socket的時候提過,Socket可以雙向通訊,所以WebSocket也是可以雙向通訊的,而在沒有雙向通訊的時候,用Http來進行雙向通訊更多的是使用長輪詢。

在WebSocket API尚未被眾多瀏覽器實現和釋出的時期,開發者在開發需要接收來自伺服器的實時通知應用程式時,不得不求助於一些“hacks”來模擬實時連線以實現實時通訊,最流行的一種方式是長輪詢。長輪詢主要是發出一個HTTP請求到伺服器,然後保持連線開啟以允許伺服器在稍後的時間響應(由伺服器確定)。為了這個連線有效地工作,許多技術需要被用於確保訊息不錯過,如需要在伺服器端快取和記錄多個的連線資訊(每個客戶)。雖然長輪詢是可以解決這一問題的,但它會耗費更多的資源,如CPU、記憶體和頻寬等,要想很好的解決實時通訊問題就需要設計和釋出一種新的協議。
WebSocket 是伴隨HTML5釋出的一種新協議。它實現了瀏覽器與伺服器全雙工通訊(full-duplex),可以傳輸基於訊息的文字和二進位制資料

WebSocket和長輪詢之間的頻寬消耗差異:

Android技能樹 — 網路小結(4)之socket/websocket/webservice

而WebSocket連線的時候,也會用到http,因為在最剛開始發出連線請求的時候,也是要藉助於現有的HTTP協議,當連線成功後,其他時候直接基於TCP完成通訊。

1.首先,客戶端發起http請求,經過3次握手後,建立起TCP連線;http請求裡存放WebSocket支援的版本號等資訊,如:Upgrade、Connection、WebSocket-Version等;
2.然後,伺服器收到客戶端的握手請求後,同樣採用HTTP協議回饋資料;
3.最後,客戶端收到連線成功的訊息後,開始藉助於TCP傳輸通道進行全雙工通訊。

Android技能樹 — 網路小結(4)之socket/websocket/webservice

當然如果只是瞭解大概的WebSocket和Http的區別,可以看這篇:WebSocket的原理,以及和Http的關係,用了通俗易懂的例子說明了,更加好記,但是並沒有說明具體的詳細內容。

詳細的可以看看這篇:
【騰雲閣】WebSocket 淺析

那我們既然是安卓開發,那我們怎麼樣使用WebSocket呢,我想現在很多人都應該網路請求這塊使用的是Okhttp吧,雖然我們平時就是用Okhttp做簡單的http/https請求,但其實它也是支援WebSocket的,具體大家可以直接搜尋相關文章

Android技能樹 — 網路小結(4)之socket/websocket/webservice

3. WebService

首先如果有人做過相關的 WebService 的話,就會覺得大體上其實和平常的 http 請求差不多,都是傳送一個請求,然後接受相應的返回資料,可能最直觀的差別是平常我們用 http 傳送請求,接收到請求/響應報文中的請求體都是 JSON,而WebService用的是 XML 的形式。其實的確是這樣,因為Webservice就是採用了基於http的soap協議傳輸資料,所以簡單理解為soap=http+xml。因為用了xml之後,更加的通用性,對於跨平臺跨應用來說都更好的相互通訊解析。

XML+XSD,SOAP和WSDL就是構成WebService平臺的三大技術。

我們具體一項項來檢視:

3.1 XML+XSD

WebService採用HTTP協議傳輸資料,採用XML格式封裝資料(即XML中說明呼叫遠端服務物件的哪個方法,傳遞的引數是什麼,以及服務物件的 返回結果是什麼)。XML是WebService平臺中表示資料的格式。除了易於建立和易於分析外,XML主要的優點在於它既是平臺無關的,又是廠商無關 的。無關性是比技術優越性更重要的:軟體廠商是不會選擇一個由競爭對手所發明的技術的。

XSD又是什麼呢,因為我們平常寫xml格式的內容,可以隨便寫,只要符合基本的xml格式就行,但實際上這樣就沒有一套標準的資料型別了。所以XML Schema(XSD)就是專門解決這個問題的一套標準。它定義了一套標準的資料型別,並給出了一種語言來擴充套件這套資料型別

Android技能樹 — 網路小結(4)之socket/websocket/webservice

3.2 SOAP

WebService通過HTTP協議傳送請求和接收結果時,傳送的請求內容和結果內容都採用XML格式封裝,並增加了一些特定的HTTP訊息頭,以說明 HTTP訊息的內容格式,這些特定的HTTP訊息頭和XML內容格式就是SOAP協議。SOAP提供了標準的RPC方法來呼叫Web Service。

所以 SOAP協議 = HTTP協議 + XML資料格式

3.3 WSDL

使用過WebService應該都知道這個,WebService務器端首先要通過一個WSDL檔案來說明有啥服務可以對外呼叫,服務是什麼(服務中有哪些方法,方法接受 的引數是什麼,返回值是什麼),服務的網路地址用哪個url地址表示,服務通過什麼方式來呼叫。

比如下面這個是國內手機號碼歸屬地查詢WEB服務:

Android技能樹 — 網路小結(4)之socket/websocket/webservice

而且提供了soap1.1/soap1.2/get/post 四種方式來呼叫獲取:

Android技能樹 — 網路小結(4)之socket/websocket/webservice
Android技能樹 — 網路小結(4)之socket/websocket/webservice
Android技能樹 — 網路小結(4)之socket/websocket/webservice

但是實際上可能沒有寫的這麼詳細,就是給我們一個WSDL,裡面的內容是這樣的:

Android技能樹 — 網路小結(4)之socket/websocket/webservice

這裡有些人可能不知道怎麼來讀懂這個檔案,其實很簡單,我們一步步來看:

  1. 我們先找到相應的service:

    Android技能樹 — 網路小結(4)之socket/websocket/webservice

    我們可以看到裡面有soap1.1,soap1.2, http-get,http-post四種,我們以soap1.2為例,我們可以看到她後面binding = "tns:MobileCodeWSSoap12",所以我們查詢相應的binding的值

  2. 我們搜尋到了MobileCodeWSSoap12後發現是:

    Android技能樹 — 網路小結(4)之socket/websocket/webservice

    所以我們要繼續跟蹤下去,這下查詢的是type="tns:MobileCodeWSSoap"

  3. 我們搜尋關鍵字:tns:MobileCodeWSSoap後發現的是:

    Android技能樹 — 網路小結(4)之socket/websocket/webservice

    我們可以看到<wsdl:operation name="getMobileCodeInfo">,所以我們知道方法名字叫getMobileCodeInfo,同時下面有 <wsdl:input message="tns:getMobileCodeInfoSoapIn"/> 和 <wsdl:output message="tns:getMobileCodeInfoSoapOut"/>
    看字面意思就知道是輸入引數和輸出引數,然後繼續對應關鍵字getMobileCodeInfoSoapIngetMobileCodeInfoSoapOut搜下

  4. 搜到的結果為:

    Android技能樹 — 網路小結(4)之socket/websocket/webservice

    ,然後繼續跟蹤getMobileCodeInfogetMobileCodeInfoResponse

  5. 最終看到了具體的輸入引數和輸出引數。

    Android技能樹 — 網路小結(4)之socket/websocket/webservice

    明顯輸入引數是mobileCode和userID,輸出引數是getMobileCodeInfoResult,而且都是字串型別。

總體來說就是 <service> -> <binding> -> <type> -> <message> -> <element>

那麼另外一個問題來了,我們從哪裡得到WSDL呢?

WSDL 檔案儲存在Web伺服器上,通過一個url地址就可以訪問到它。客戶端要呼叫一個WebService服務之前,要知道該服務的WSDL檔案的地址。比如上面我貼圖的WSDL內容就是隻要訪問:ws.webxml.com.cn/WebServices…就可以了。

WebService服務提供商可以通過兩種方式來暴露它的WSDL檔案地址:1.註冊到UDDI伺服器,以便被人查詢;2.直接告訴給客戶端呼叫者。

補充1 :可能有些人會說WSDL的內容還是看不懂,可以參考 WSDL 教程WebService中的WSDL詳細解析 學習。

Android技能樹 — 網路小結(4)之socket/websocket/webservice

補充2 : 剛提到了Soap1.1 和 Soap1.2:

Android技能樹 — 網路小結(4)之socket/websocket/webservice
Android技能樹 — 網路小結(4)之socket/websocket/webservice
Android技能樹 — 網路小結(4)之socket/websocket/webservice

結語:

emmmm…….輕噴即可。有錯請留言,我可以進行修改。其中文章配圖部分引自下面參考文章。

參考文章:

張大胖的socket

Android:這是一份很詳細的Socket使用攻略

WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)

【騰雲閣】WebSocket 淺析

WebService學習總結(一)——WebService的相關概念

WebService基礎學習(一)—基礎知識

WebService中的WSDL詳細解析

WebService就是這麼簡單

WebService中的WSDL詳細解析

相關文章