TCP/IP、Http、Socket、XMPP-從入門到深入


TCP/IP、Http、Socket、XMPP-從入門到深入

為了便於大家理解和記憶,我們先對這幾個概念進行的介紹,然后分析他們的不同,再進行詳細的分析。

一、TCP/IP簡介

IP協議是網絡層,TCP協議是傳輸層,HTTP協議是應用層,socket是對TCP/IP協議的代碼封裝和應用。

TPC/IP 主要解決數據如何在網絡中傳輸,HTTP主要解決如何包裝數據。

TCP/IP協議用來傳輸數據,應用層協議 使傳輸的數據有意義,應用層協議有很多,比如HTTP、FTP、TELNET等,也可以自己定義應用層協議。

比如:網頁使用HTTP協議 封裝HTTP文本信息,再用TCP/IP做傳輸層協議將它傳送到瀏覽器。

二、Socket簡介

Socket不是協議,而是一個可以調用的接口(API)。我們通過Socket,才能使用TCP/IP協議。

Socket跟TCP/IP協議沒有必然的聯系。Socket編程接口在設計的時候,就希望也能適應其他的網絡協議。所以說,Socket的出現只是使得程序員更方便地使用TCP/IP協議棧而已,是對TCP/IP協議的抽象,從而形成了我們知道的一些最基本的函數接口,比如create、listen、connect、accept、send、read和write等等。

TCP/IP只是協議,必須要具體實現,還要提供對外的操作接口,這就是Socket編程接口。Socket本身不算是協議,就像上面所說,它只是提供了一個針對TCP或者UDP編程的接口。

三 、 TCP三次握手 簡介

第一次握手:客戶端發送包到服務器,等待服務器確認;

第二次握手:服務器收到並確認客戶端的數據包,同時自己也發送一個數據吧回復給客戶端;

第三次握手:客戶端收到服務器的數據包,向服務器發送確認包,此包發送完畢,就完成了三次握手。

先來個形象的比喻:我(客戶端)發了個郵件給你(服務端),(上面這是第一次握手),但是我不知道你收到沒有,所以你發了個“我已經收到”的郵件回復給我(這是第二次握手)。我收到了你的郵件,但是你不知道 我到底有沒有收到你的這封郵件,所以你不確定 我到底知不知道“你已經收到”。所以 我還要再發送個郵件 告知你 我收到郵件了(這是第三次握手)。。

這樣就能確認彼此之間的通訊是正常的。

握手過程中傳送的包里不包含數據,三次握手完畢后,客戶端與服務器才正式開始傳送數據。

理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去。

斷開連接時服務器和客戶端均可以主動發起斷開TCP連接的請求,斷開過程需要經過“四次握手”。

四、Socket網絡連接的步驟

建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於服務器端,稱為ServerSocket 。

套接字之間的連接過程分為三個步驟:服務器監聽,客戶端請求,連接確認。

1、服務器監聽:服務器端 實時監控網絡狀態,處於等待連接的狀態,等待客戶端的連接請求。

2、客戶端請求:客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。客戶端的套接字必指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。

3。連接確認:當服務器端套接字監聽到客戶端套接字的請求時,就建立一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續監聽其他客戶端的連接請求。

五、HTTP簡介

HTTP(Hypertext Transfer Protocol ) 超文本傳送協議,是建立在TCP協議之上的一種應用協議。

客戶端發送的每次請求都需要服務器響應,在請求結束后,會主動釋放連接。從建立連接到關閉連接的過程稱為“一次連接”。

六 . TCP和UDP的區別

TCP是面向鏈接的,雖然說網絡的不安全不穩定特性決定了多少次握手都不能保證連接的可靠性,但TCP的三次握手在最低限度上,也很大程度上 保證了連接的可靠性;

而UDP傳送數據前並不與對方建立連接,對接收到的數據也不發送確認信號,發送端不知道數據是否會正確接收,當然也不用重發,UDP是無連接的、不可靠的一種數據傳輸協議。

所以UDP的開銷更小數據傳輸速率更高,實時性更好。

所以采用TCP傳輸協議的MSN比采用UDP的QQ傳輸文件慢,但並不能說QQ的通信是不安全的,因為程序員可以手動對UDP的數據收發進行驗證,比如發送方對每個數據包進行編號然后由接收方進行驗證啊什么的。

七 . XMPP簡介

XMPP(Extensible Messaging and Presence Protocol,前稱Jabber)是一種以XML為基礎的開放式即時通信協議,是經由互聯網工程工作小組(IETF)通過的互聯網標准。

XMPP網絡是基於服務器的,即客戶端之間彼此不直接交談。

1、XMPP實際是怎么運行的,舉個栗子

Jabber識別符(JID)是用戶登錄時所使用的賬號,通常像一個電子郵件地址,如someone@example.com;前部分為用戶名,后部分為XMPP服務器域名。

假設朱麗葉(juliet@capulet.com)想和羅密歐(romeo@montague.net)通話,他們兩人的賬號分別在 A.com 及 B.net 的服務器上。當朱麗葉輸入消息並按下發送鈕之后:

朱麗葉的XMPP客戶端將她的消息發送到A.com XMPP服務器。

A.com XMPP服務器打開與B.net XMPP服務器的連接。

B.net XMPP服務器將消息寄送給羅密歐。如果他目前不在在線,那么存儲消息以待稍后寄送。

羅密歐與朱麗葉兩人的XMPP服務是由兩家不同的企業所提供的,而他們彼此傳訊時,不須擁有對方服務器的賬號,也不須成為對方企業的會員。

2、XMPP特性

XMPP因為被Google Talk應用而被廣大網民所接觸。

XMPP與IMPP、PRIM、SIP(SIMPLE)合稱四大IM協議主流,在此4大協議中,XMPP是最靈活的。

分布式:XMPP網絡的架構和電子郵件十分相像;XMPP核心協議通信方式是先創建一個stream,XMPP以TCP傳遞XML數據流,沒有中央主服務器。任何人都可以運行自己的XMPP服務器,使個人及組織能夠掌控他們的即時傳訊體驗。

彈性佳:XMPP除了用在即時通信,還能用在網絡管理、內容供稿、協同工具、文件共享、游戲、遠程系統監控等。

安全:XMPP協議的服務器可以獨立於公眾XMPP網絡(例如在企業內部網絡中),而使用SASL及TLS等技術的可靠安全性,已內置於核心XMPP技術規格中。

3、與其他協議互聯

XMPP協議的另一功能是運輸(transports),也被稱為網關(gateways),可允許用戶通過網絡使用其它協議。這可以是其他的即時通信協議,也可以是不同協議,如短信(SMS)或電子郵件。

各IM之間的互傳:

TCP/IP、Http、Socket、XMPP-從入門到深入

4、XMPP協議通過HTTP運輸

XMPP協議可以使用HTTP的方式有兩種:輪詢(polling)與綁定(binding)。

輪詢現在不推薦,輪詢:HTTP郵件存儲在服務器端的數據庫上,客戶端必須一再地以HTTP的GET和POST的方式去抓取(以及刊出)其中的消息。

綁定的方式:客戶端會保留一個長存的HTTP連接,等待一旦服務器有新的消息時,就立刻接收消息。因為輪詢的結果往往是服務端沒有新消息,這種推送的通知模式比輪詢的方式更有效率。

5、再舉個栗子,使用XMPP協議的客戶端1與服務器端對話 :

客戶端1 連接到一個XMPP服務器,發送一條消息(主題和內容均為“test 1449”)到客戶端2,然后注銷。

  • 客戶端1:

<?xml version="1.0"?>

<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" to="XMPP服務器">

  • XMPP服務器:

<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' from='XMPP服務器' id='1461777714'>

  • 客戶端1:

<iq type="set" id="auth_2" to="XMPP服務器" >

<query xmlns="jabber:iq:auth">

<username>客戶端1</username>

<password>mypassword</password>

<resource>Work</resource>

</query>

</iq>

  • XMPP服務器:

<iq from="XMPP服務器" id='auth_2' type='result'/>

  • 客戶端1:

<message to="客戶端2@example.com" >

<subject>test 1449</subject>

<body>test 1449</body>

</message>

<presence type="unavailable" >

<status>Logged out</status>

</presence>

</stream:stream>

  • XMPP服務器:

</stream:stream>


八、TCP/IP深入

1、TCP/IP數據格式

TCP/IP、Http、Socket、XMPP-從入門到深入

便於大家觀看,下面是翻譯成中文后的圖片:

TCP/IP、Http、Socket、XMPP-從入門到深入

每個字段的意思:

  • Source Port(源端口)和Destination Port(目的端口):分別占用16位,用於區別主機中的不同進程,而IP地址是用來區分不同的主機的,源端口號和目的端口號配合上IP首部中的源IP地址和目的IP地址就能唯一的確定一個TCP連接。

  • Sequence Number(數據序號):用來標識從TCP發端向TCP收端 發送的數據字節流,它表示在這個報文段中的第一個數據字節在數據流中的序號;主要用來解決網絡報亂序的問題。

  • Acknowledgment Number(確認序號):32位,包含發送確認的一端所期望收到的下一個序號,因此,確認序號應當是上次已成功收到數據字節序號加1。不過,只有當標志位中的ACK標志(下面介紹)為1時該確認序列號的字段才有效。主要用來解決不丟包的問題;

  • Offset(偏移):給出首部中32 bit字的數目,需要這個值是因為任選字段的長度是可變的。這個字段占4bit(最多能表示15個32bit的的字,即4*15=60個字節的首部長度),因此TCP最多有60字節的首部。然而,沒有任選字段,正常的長度是20字節;

  • TCP Flags: TCP首部中有6個標志比特,它們中的多個可同時被設置為1,主要是用於操控TCP的狀態機的,依次為URG,ACK,PSH,RST,SYN,FIN。每個標志位的意思如下:

URG:此標志表示TCP包的緊急指針域(后面馬上就要說到)有效,用來保證TCP連接不被中斷,並且督促中間層設備要盡快處理這些數據;

ACK:此標志表示應答域有效,就是說前面所說的TCP應答號將會包含在TCP數據包中;有兩個取值:0和1,為1的時候表示應答域有效,反之為0;

PSH:這個標志位表示Push操作。就是指在數據包到達接收端以后,立即傳送給應用程序,而不是在緩沖區中排隊;

RST:這個標志表示連接復位請求。用來復位那些產生錯誤的連接,也被用來拒絕錯誤和非法的數據包;

SYN:表示同步序號,用來建立連接。SYN標志位和ACK標志位搭配使用,當連接請求的時候,SYN=1,ACK=0;連接被響應的時候,SYN=1,ACK=1;這個標志的數據包經常被用來進行端口掃描。掃描者發送一個只有SYN的數據包,如果對方主機響應了一個數據包回來 ,就表明這台主機存在這個端口;但是由於這種掃描方式只是進行TCP三次握手的第一次握手,因此這種掃描的成功表示被掃描的機器不很安全,一台安全的主機將會強制要求一個連接嚴格的進行TCP的三次握手;

FIN: 表示發送端已經達到數據末尾,也就是說雙方的數據傳送完成,沒有數據可以傳送了,發送FIN標志位的TCP數據包后,連接將被斷開。這個標志的數據包也經常被用於進行端口掃描。

  • Window:窗口大小,也就是有名的滑動窗口,用來進行流量控制;這是一個復雜的問題。

2、TCP/IP 三次握手

TCP協議之所以能提供可靠的連接 是因為三次握手。三次握手的目的是同步連接雙方的序列號和確認號並交換 TCP窗口大小信息。

TCP/IP、Http、Socket、XMPP-從入門到深入

先簡單說下上圖中的 seq表示:Sequence Number(數據序號)。SYN:表示同步序號。ACK:不是TCP Flags里的標志,而是指Acknowledgment Number(確認序號)。

第一次握手:客戶端發送連接請求報文段,將SYN位置為1,Sequence Number(數據序號)為x;然后,客戶端進入SYN_SEND狀態,等待服務器的確認;

第二次握手:服務器收到客戶端的SYN報文段,對這個SYN報文段進行確認,設置Acknowledgment Number(確認序號)為x+1(Sequence Number+1);同時,自己自己還要發送SYN請求信息,將SYN位置為1,Sequence Number為y;服務器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一並發送給客戶端,此時服務器進入SYN_RECV狀態;

第三次握手:客戶端收到服務器的SYN+ACK報文段。然后將Acknowledgment Number設置為y+1,向服務器發送ACK報文段,這個報文段發送完畢以后,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。

那么如果三次握手改成二次握手 會現在啥問題: 已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤。詳解:

  • client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放 后 才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認為是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不采用“三次握手”,那么只要server發出確認,新的連接就建立了。

  • 由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以為新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。”

4、三次握手后就可以傳送數據了。數據傳送完畢后,就要斷開TCP連接了,這就是TCP的第四次分手。

第一次分手:主機1(可以是客戶端 或者 服務器端),設置Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;

第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我“同意”你的關閉請求;

第三次分手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST_ACK狀態;

第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然后主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以后,就關閉連接;此時,主機1等待2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

5、分個手也要四次,煩不煩,看看為啥分手要這么麻煩:

TCP協議是一種面向連接的、可靠的、基於字節流的運輸層通信協議。

TCP是全雙工模式,這就意味着,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;然后主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之后彼此就 中斷了這次TCP連接。

6、四次分手過程中的狀態變化。

FIN_WAIT_1: 其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。(主動方)

FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你(ACK信息),稍后再關閉連接。(主動方)

CLOSE_WAIT:表示在等待關閉。當對方close一個SOCKET后發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那么你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。(被動方)

LAST_ACK: 它是被動關閉一方在發送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態了。(被動方)

TIME_WAIT: 表示收到了對方的FIN報文,並發送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)

CLOSED: 表示連接中斷。

九、HTTP詳解

1、HTTP協議永遠都是客戶端發起請求,服務器回送響應。一個客戶端向服務器端發出請求,然后服務器返回響應(response),連接就被關閉了。

TCP/IP、Http、Socket、XMPP-從入門到深入

2、做過Socket編程的人都知道,消息頭/消息體”的分割方式是很常用的,消息頭告訴對方這個消息是干什么的,消息體告訴對方怎么干。每一個HTTP包都分為HTTP頭和HTTP體兩部分,消息體是可選的,而消息頭是必須的。每當我們打開一個網頁,

HTTP 請求由三部分組成:請求行、 請求頭和請求正文。請求行是指請求方法 URI 協議/版本,

格式如:POST /index.php HTTP/1.1 也就是:請求方式 /URL 協議/協議的版本。

3、請求方式

HTTP/2:這個版本是 2015年5月正式發布。HTTP/2通過支持請求與相應的多路重用來減少延遲,通過壓縮HTTP頭字段將協議開銷降到最低,同時增加了對請求優先級和服務器端推送的支持。

HTTP/1.1協議中共定義了8種HTTP請求方法。

  • GET:GET請求會顯示請求指定的資源。一般來說GET方法應該只用於數據的讀取,而不應當用於會產生副作用的非冪等的操作中。

GET會方法請求指定的頁面信息,並返回響應主體,GET被認為是不安全的方法,因為GET方法會被網絡蜘蛛等任意的訪問。

  • HEAD:HEAD方法與GET方法一樣,都是向服務器發出指定資源的請求。但是,服務器在響應HEAD請求時不會回傳資源的內容部分,即:響應主體。這樣,我們可以不傳輸全部內容的情況下,就可以獲取服務器的響應頭信息。HEAD方法常被用於客戶端查看服務器的性能。

  • POST:POST請求會 向指定資源提交數據,請求服務器進行處理,如:表單數據提交、文件上傳等,請求數據會被包含在請求體中。POST方法是非冪等的方法,因為這個請求可能會創建新的資源或/和修改現有資源。

  • PUT:PUT請求會身向指定資源位置上傳其最新內容,PUT方法是冪等的方法。通過該方法客戶端可以將指定資源的最新數據傳送給服務器取代指定的資源的內容。

  • DELETE:DELETE請求用於請求服務器刪除所請求URI(統一資源標識符,Uniform Resource Identifier)所標識的資源。DELETE請求后指定資源會被刪除,DELETE方法也是冪等的。

  • CONNECT:CONNECT方法是HTTP/1.1協議預留的,能夠將連接改為管道方式的代理服務器。通常用於SSL加密服務器的鏈接與非加密的HTTP代理服務器的通信。

  • OPTIONS:OPTIONS請求與HEAD類似,一般也是用於客戶端查看服務器的性能。 這個方法會請求服務器返回該資源所支持的所有HTTP請求方法,該方法會用'*'來代替資源名稱,向服務器發送OPTIONS請求,可以測試服務器功能是否正常。JavaScript的XMLHttpRequest對象進行CORS跨域資源共享時,就是使用OPTIONS方法發送嗅探請求,以判斷是否有對指定資源的訪問權限。 允許

  • TRACE:TRACE請求服務器回顯其收到的請求信息,該方法主要用於HTTP請求的測試或診斷。

4、在HTTP/1.1標准制定之后,又陸續擴展了一些方法。其中使用中較多的是PATCH 方法:

  • PATCH:PATCH方法在2010年的RFC 5789標准中被定義。PATCH請求與PUT請求類似,同樣用於資源的更新。二者有以下兩點不同:

PATCH一般用於資源的部分更新,而PUT一般用於資源的整體更新。

當資源不存在時,PATCH會創建一個新的資源,而PUT只會對已在資源進行更新。

5、冪等性(Idempotence)

HTTP方法的冪等性是指一次和多次請求某一個資源應該具有同樣的副作用。冪等性屬於語義范疇,正如編譯器只能幫助檢查語法錯誤一樣,HTTP規范也沒有辦法通過消息格式等語法手段來定義它,這可能是它不太受到重視的原因之一。但實際上,冪等性是分布式系統設計中十分重要的概念,而HTTP的分布式本質也決定了它在HTTP中具有重要地位。

HTTP協議本身是一種面向資源的應用層協議,但對HTTP協議的使用實際上存在着兩種不同的方式:一種是RESTful的,它把HTTP當成應用層協議,比較忠實地遵守了HTTP協議的各種規定;另一種是SOA的,它並沒有完全把HTTP當成應用層協議,而是把HTTP協議作為了傳輸層協議,然后在HTTP之上建立了自己的應用層協議。HTTP冪等性主要針對RESTful風格的,冪等性並不屬於特定的協議,它是分布式系統的一種特性;所以,不論是SOA還是RESTful的Web API設計都應該考慮冪等性。下面將介紹HTTP GET、DELETE、PUT、POST四種主要方法的語義和冪等性。

HTTP GET方法用於獲取資源,不應有副作用,所以是冪等的。

HTTP DELETE方法用於刪除資源,有副作用,但它應該滿足冪等性。比如:DELETE http://www.xxxxx.com/article/4231,調用一次和N次對系統產生的副作用是相同的,即刪掉id為4231的帖子;因此,調用者可以多次調用或刷新頁面而不必擔心引起錯誤。

比較容易混淆的是HTTP POST和PUT。POST和PUT的區別容易被簡單地誤認為“POST表示創建資源,PUT表示更新資源”;而實際上,二者均可用於創建資源,更為本質的差別是在冪等性方面。在HTTP規范中對POST和PUT是這樣定義的:

POST所對應的URI並非創建的資源本身,而是資源的接收者。比如用POST提交帖子,兩次相同的POST請求會在服務器端創建兩份資源,它們具有不同的URI;所以,POST方法不具備冪等性。而PUT所對應的URI是要創建或更新的資源本身。比如:PUT 創建或更新ID為4231的帖子。對同一URI進行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有冪等性。

比如,論壇網站中防止意外的重復發帖:

用POST 來實現發帖;用PUT 來實現更新帖。

本文為頭條號作者發布,不代表今日頭條立場。

收藏
舉報
 

16 條評論
 
評論
  • 寫的不錯,支持!

     
  • 相當不錯,正在學習這方面的知識。謝謝

     
  • 支持作者寫的真不錯

     
  • 大家多多收藏。謝謝

     
  • 英文代碼太多,誰能記住,那個層面都是看不見的東西,通訊系統的東西要從基礎積累經驗,尤其這些代碼都是英文,很容易混淆,


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM