介於本身的網絡方面知識爛的一塌糊塗,因此準備寫相關網絡的文章,可是考慮所有寫在一篇太長了,因此分開寫,但願你們能仔細看,最好能夠指出個人錯誤,讓我也能糾正。html
1.講解相關的整個網絡體系結構:web
2.講解相關網絡的重要知識點,好比不少人都聽過相關網絡方面的名詞,可是僅限於聽過而已,什麼tcp ,udp ,socket ,websocket, http ,https ,而後webservice是啥,跟websocket很像,socket和websocket啥關係長的也很像,session,token,cookie又是啥。編程
Android技能樹 — 網絡小結(2)之TCP/UDPapi
Android技能樹 — 網絡小結(3)之HTTP/HTTPS瀏覽器
Android技能樹 — 網絡小結(4)之socket/websocket/webservice緩存
相關網絡知識點小結- cookie/session/token(待寫)bash
3.相關的第三方框架的源碼解析,畢竟如今面試個大點的公司,okhttp和retrofit源碼是必問的。服務器
Android技能樹 — 網絡小結(6)之 OkHttp超超超超超超超詳細解析websocket
Android技能樹 — 網絡小結(7)之 Retrofit源碼詳細解析
咱們在網絡體系結構小結中提過,TCP/IP的體系結構圖爲
在傳輸層中爲TCP和UDP,解決了數據之間的運輸,可是咱們不多直接去調用TCP和UDP,好比咱們如今是要用TCP傳輸數據,你要寫代碼去進行TCP的三次握手鍊接和四次揮手斷開等,並且可能還要考慮什麼滑動窗口,累積確認、分組緩存、流量控制等?因此咱們正須要某個類,這個類幫咱們封裝好了TCP的鏈接,傳輸,斷開等一系列相關各種操做,是否是就很方便了。沒錯,這個類就是Socket。
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個元素來肯定。
具體的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的一個很大的特色就是服務端和客戶端能夠相互傳數據。
這和咱們平時的網絡交互差異挺大的,畢竟咱們日常訪問後臺接口,不多說後臺忽然經過這個接口發個數據給客戶端是吧,通常都是客戶端主動發送接口請求,而後才能拿到相關數據。
咱們在上面的Socket的相關介紹能夠看到,Socket是在運輸層作了一層抽象層,是TCP/UDP 的 api工具類,因此Socket不算是應用層類,而咱們在相關網絡知識點小結- http/https提過Http/Https是屬於應用層的,而咱們的WebSocket也是屬於應用層的。因此說WebSocket和Http/Https是同一層級的。
而咱們也常常看到不少所謂的Http與WebSocket的區別文章等,好比:
而咱們在上面介紹Socket的時候提過,Socket能夠雙向通訊,因此WebSocket也是能夠雙向通訊的,而在沒有雙向通訊的時候,用Http來進行雙向通訊更多的是使用長輪詢。
在WebSocket API還沒有被衆多瀏覽器實現和發佈的時期,開發者在開發須要接收來自服務器的實時通知應用程序時,不得不求助於一些「hacks」來模擬實時鏈接以實現實時通訊,最流行的一種方式是長輪詢。長輪詢主要是發出一個HTTP請求到服務器,而後保持鏈接打開以容許服務器在稍後的時間響應(由服務器肯定)。爲了這個鏈接有效地工做,許多技術須要被用於確保消息不錯過,如須要在服務器端緩存和記錄多個的鏈接信息(每一個客戶)。雖然長輪詢是能夠解決這一問題的,但它會耗費更多的資源,如CPU、內存和帶寬等,要想很好的解決實時通訊問題就須要設計和發佈一種新的協議。 WebSocket 是伴隨HTML5發佈的一種新協議。它實現了瀏覽器與服務器全雙工通訊(full-duplex),能夠傳輸基於消息的文本和二進制數據
WebSocket和長輪詢之間的帶寬消耗差別:
而WebSocket鏈接的時候,也會用到http,由於在最剛開始發出鏈接請求的時候,也是要藉助於現有的HTTP協議,當鏈接成功後,其餘時候直接基於TCP完成通訊。
1.首先,客戶端發起http請求,通過3次握手後,創建起TCP鏈接;http請求裏存放WebSocket支持的版本號等信息,如:Upgrade、Connection、WebSocket-Version等;
2.而後,服務器收到客戶端的握手請求後,一樣採用HTTP協議回饋數據;
3.最後,客戶端收到鏈接成功的消息後,開始藉助於TCP傳輸信道進行全雙工通訊。
固然若是隻是瞭解大概的WebSocket和Http的區別,能夠看這篇:WebSocket的原理,以及和Http的關係,用了通俗易懂的例子說明了,更加好記,可是並無說明具體的詳細內容。
詳細的能夠看看這篇: 【騰雲閣】WebSocket 淺析
那咱們既然是安卓開發,那咱們怎麼樣使用WebSocket呢,我想如今不少人都應該網絡請求這塊使用的是Okhttp吧,雖然咱們平時就是用Okhttp作簡單的http/https請求,但其實它也是支持WebSocket的,具體你們能夠直接搜索相關文章
首先若是有人作過相關的 WebService 的話,就會以爲大致上其實和日常的 http 請求差很少,都是發送一個請求,而後接受相應的返回數據,可能最直觀的差異是日常咱們用 http 發送請求,接收到請求/響應報文中的請求體都是 JSON,而WebService用的是 XML 的形式。其實的確是這樣,由於Webservice就是採用了基於http的soap協議傳輸數據,因此簡單理解爲soap=http+xml。由於用了xml以後,更加的通用性,對於跨平臺跨應用來講都更好的相互通訊解析。
XML+XSD,SOAP和WSDL就是構成WebService平臺的三大技術。
咱們具體一項項來查看:
WebService採用HTTP協議傳輸數據,採用XML格式封裝數據(即XML中說明調用遠程服務對象的哪一個方法,傳遞的參數是什麼,以及服務對象的 返回結果是什麼)。XML是WebService平臺中表示數據的格式。除了易於創建和易於分析外,XML主要的優勢在於它既是平臺無關的,又是廠商無關 的。無關性是比技術優越性更重要的:軟件廠商是不會選擇一個由競爭對手所發明的技術的。
XSD又是什麼呢,由於咱們日常寫xml格式的內容,能夠隨便寫,只要符合基本的xml格式就行,但實際上這樣就沒有一套標準的數據類型了。因此XML Schema(XSD)就是專門解決這個問題的一套標準。它定義了一套標準的數據類型,並給出了一種語言來擴展這套數據類型
WebService經過HTTP協議發送請求和接收結果時,發送的請求內容和結果內容都採用XML格式封裝,並增長了一些特定的HTTP消息頭,以說明 HTTP消息的內容格式,這些特定的HTTP消息頭和XML內容格式就是SOAP協議。SOAP提供了標準的RPC方法來調用Web Service。
因此 SOAP協議 = HTTP協議 + XML數據格式
使用過WebService應該都知道這個,WebService務器端首先要經過一個WSDL文件來講明有啥服務能夠對外調用,服務是什麼(服務中有哪些方法,方法接受 的參數是什麼,返回值是什麼),服務的網絡地址用哪一個url地址表示,服務經過什麼方式來調用。
好比下面這個是國內手機號碼歸屬地查詢WEB服務:
並且提供了soap1.1/soap1.2/get/post 四種方式來調用獲取:
可是實際上可能沒有寫的這麼詳細,就是給咱們一個WSDL,裏面的內容是這樣的:
這裏有些人可能不知道怎麼來讀懂這個文件,其實很簡單,咱們一步步來看:
咱們先找到相應的service:
咱們能夠看到裏面有soap1.1,soap1.2, http-get,http-post四種,咱們以soap1.2爲例,咱們能夠看到她後面binding = "tns:MobileCodeWSSoap12"
,因此咱們查找相應的binding的值 咱們搜索到了MobileCodeWSSoap12
後發現是:
type="tns:MobileCodeWSSoap"
咱們搜索關鍵字:tns:MobileCodeWSSoap
後發現的是:
<wsdl:operation name="getMobileCodeInfo">
,因此咱們知道方法名字叫getMobileCodeInfo
,同時下面有 <wsdl:input message="tns:getMobileCodeInfoSoapIn"/> 和 <wsdl:output message="tns:getMobileCodeInfoSoapOut"/>
看字面意思就知道是輸入參數和輸出參數,而後繼續對應關鍵字getMobileCodeInfoSoapIn
和getMobileCodeInfoSoapOut
搜下 搜到的結果爲:
,而後繼續跟蹤getMobileCodeInfo
和getMobileCodeInfoResponse
。 最終看到了具體的輸入參數和輸出參數。
明顯輸入參數是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詳細解析 學習。
補充2 : 剛提到了Soap1.1 和 Soap1.2:
emmmm.......輕噴便可。有錯請留言,我能夠進行修改。其中文章配圖部分引自下面參考文章。
參考文章:
WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)