Socket實現簡單的聊天功能,我們先來看下效果:
通過這張圖,我們更容易的去理解這些API,客戶端和服務端的不同點就是建立連接部分。服務端需要bind listen accept ,多個客戶端可以連接一個服務端。
? ? 1>? domain:協議域,又稱協議族(family)。常用的協議族有AF_INET、AF_INET6、AF_LOCAL(或稱AF_UNIX,Unix域Socket)、AF_ROUTE等。協議族決定了socket的地址類型。
?? ? 2> type:指定Socket類型。常用的socket類型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一種面向連接的Socket,針對于面向連接的TCP服務應用。數據報式Socket(SOCK_DGRAM)是一種無連接的Socket,對應于無連接的UDP服務應用。
?? ? 3>?protocol:指定協議。常用協議有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分別對應TCP傳輸協議、UDP傳輸協議、STCP傳輸協議、TIPC傳輸協議。
?? ? 注意:1.type和protocol不可以隨意組合,如SOCK_STREAM不可以跟IPPROTO_UDP組合。當第三個參數為0時,會自動選擇第二個參數類型對應的默認協議。
?? ? 返回值:?如果調用成功就返回新創建的套接字的描述符,如果失敗就返回INVALID_SOCKET(Linux下失敗返回-1)?*/
? ? ?socket(AF_INET, SOCK_STREAM, 0);
1>?套接字描述符
2>?指向數據結構sockaddr的指針,其中包括目的端口和IP地址
3>?參數二sockaddr的長度,可以通過sizeof(struct sockaddr)獲得
返回值:成功則返回0,失敗返回非0,錯誤碼GetLastError()
?connect(self.mSocketId,(conststructsockaddr*)&socket_add,sizeof(socket_add));
? ? ?1> 套接字描述符
?? ? 2> 指向數據結構sockaddr的指針,其中包括目的端口和IP地址
?? ? 3> sockaddr的長度,可以通過sizeof(struct sockaddr)獲得
? ? ?返回值:? 成功則返回0,失敗返回非0,錯誤碼GetLastError()。
? ? ?bind(mSocketId, (const?struct?sockaddr?*)&socket_add,?sizeof(socket_add));
????1>?套接字描述符
?????2> 最大支持連接數
?? ? 返回值:如果失敗則返回?-1?
????listen(mSocketId, MaxConnectCount);
????1> 客戶端socket
?? ? 2> 指向數據結構sockaddr的指針
?? ? 返回值:失敗則返回?-1 SOCKET_ERROR,成功返回客戶端編號
? ? ?accept(mSocketId, (structsockaddr*)&client_addr, &addr_length);
?? ? ?1>? ?一個用于標識已連接套接口的描述字。
?? ? ?2>? 包含待發送數據的緩沖區。
?? ? ?3>? 緩沖區中數據的長度。
? ? ??4>? 調用執行方式。
? ? ? 返回值:如果成功,則返回發送的字節數,失敗則返回SOCKET_ERROR
? ? ? 一個中文對應 3 個字節!UTF8 編碼!
? ? ??send(mSocketId, send_msg, strlen(send_msg), 0);
????1> 客戶端socket????????
?? ? 2> 接收內容緩沖區地址
?? ? 3> 接收內容緩存區長度
?? ? 4> 接收方式,0表示阻塞,必須等待服務器返回數據
? ? ?返回值:如果成功,則返回讀入的字節數,失敗則返回?-1?SOCKET_ERROR
? ? ? recv(mSocketId, buffer,sizeof(buffer),0);
TCP三次握手
連接上Socket后,發消息時,用Wireshark網絡封包分析工具,抓到以下數據。我們來看一下TCP的三次握手。
TCP是因特網中的傳輸層協議,使用三次握手協議建立連接。
當主動方發出SYN連接請求后,等待對方回答TCP的三次握手SYN+ACK ,并最終對對方的 SYN 執行 ACK 確認。
這種建立連接的方法可以防止產生錯誤的連接,TCP使用的流量控制協議是可變大小的滑動窗口協議。
IP層協議屬于不可靠的協議,IP層并不關心數據是否發送到了對端,TCP通過確認機制來保證數據傳輸的可靠性?
TCP三次握手的過程如下:
(1)客戶端發送SYN(SEQ=x)報文給服務器端,進入SYN_SEND狀態。
(2)服務器端收到SYN報文,回應一個SYN (SEQ=y)ACK(ACK=x+1)報文,進入SYN_RECV狀態。
(3)客戶端收到服務器端的SYN報文,回應一個ACK(ACK=y+1)報文,進入Established狀態。
TCP Window Update 滑動窗口,在一個文件傳輸的時候, 數據接收方需要阻止它的TCP Window降為0, 意味著window填滿了. 如果一個TCP Window變為0了, 或者接近0了, 這就會警告數據發送方沒有更多空間來接受更多數據了.文件傳輸會停止, 直到收到一個update說明buffer已經清空了.
Frame:Frame是幀,數據單元,對應物理層。
LoopBack:對應數據鏈路層,以太網卡等,這里用的本地回環地址LoopBack。
IPV4:對應網絡層,IP協議(協議棧可以想象成漏斗型,IP在中間作為上下層的連接點),Src:源地址 Dst:目標地址,IP層協議層無端口
TCP:進入TCP層,有端口,對應傳輸層。
滑動窗口
用上面藍色線代表服務端,下面代表客戶端。中間箭頭代表發起和響應的網絡請求。綠色框代表滑動窗口。
滑動窗口是控制接收以及同步數據范圍的,通知發送端目前接收的數據范圍,用于流量控制,接收端使用。
擁塞窗口是控制發送速率的,避免發的過多,發送端使用。
兩個窗口的維護是獨立的,滑動窗口主要由接收方反饋緩存情況來維護,擁塞窗口主要由發送方的擁塞控制算法檢測出的網絡擁塞程度來決定的。
TCP四次揮手
斷開連接時,用Wireshark網絡封包分析工具,抓到了TCP的四次揮手
(1) 關閉時首先調用close,稱該端執行“主動關閉”(active close)。該端的TCP于是發送一個FIN分節,表示數據發送完畢。
(2) 接收到這個FIN的對端執行 “被動關閉”(passive close),這個FIN由TCP確認。
注意:FIN的接收也作為一個文件結束符(end-of-file)傳遞給接收端應用進程,放在已排隊等候該應用進程接收的任何其他數據之后,因為,FIN的接收意味著接收端應用進程在相應連接上再無額外數據可接收。
(3) 一段時間后,接收到這個文件結束符的應用進程將調用close關閉它的套接字。這導致它的TCP也發送一個FIN。
(4) 接收這個最終FIN的原發送端TCP(即執行主動關閉的那一端)確認這個FIN。
TCP 和 UDP
TCP:(傳輸控制協議)
TCP的優點: 穩定?TCP的可靠體現在TCP在傳遞數據之前,通過三次握手建立連接,形成傳輸數據的通道,四次揮手完成斷開,是可靠協議,安全送達。
在連接中進行大數據傳輸(數據大小不受限制)TCP保證數據順序,UDP不保證。
缺點:必須建立連接,效率會稍低。
應用場景: 下載數據
UDP(用戶數據協議)
速度快,UDP沒有TCP的握手,UDP是一個無狀態的傳輸協議,不需要建立連接,所以它在傳遞數據時非常快。
只管發送,不確認對方是否接收到,將數據及源和目的封裝成數據包中,每個數據報的大小限制在64k之間。
缺點:不需要建立連接,因此是不可靠協議,會丟包。
應用場景:流媒體數據傳輸,直播時界面會模糊,馬賽克的感覺(數據丟幀)?QQ語音?QQ視頻?王者榮耀等也是UDP
OSI網絡模型(太官方不太懂,舉個例子一下就明白了)
物理層:主要定義物理設備標準,如網線的接口類型、光纖的接口類型、各種傳輸介質的傳輸速率等。它的主要作用是傳輸比特流(就是1、0轉化為電流的強弱來進行傳輸,到達目的地后再轉化為1、0,也就是我們常說的數模轉換與模數轉換)。這一層的數據叫做比特。
例:數據在電線傳輸過程中,用電流的高低頻代表 01 二進制數據,但是電信號容易收到影響(數據傳輸中需要打包,有種格式叫 :標準幀格式。物理層(電線)
數據鏈路層:定義了如何格式化數據以進行傳輸,以及如何讓控制對物理介質的訪問。這一層通常還提供錯誤檢測和糾正,以確保數據的可靠傳輸。
例:?數據鏈路層(數據打包的過程)
網絡層:在位于不同地理位置的網絡中的兩個主力系統之間提供連接和路徑選擇。Internet的發展使得從世界各站點訪問信息的用戶數量大大增加,而網絡層正是管理這種連接的層。
例:網絡層( 選擇數據傳輸路徑,路由器)
傳輸層:定義了一些傳輸數據的協議和端口號(WWW端口80等),如:TCP(傳輸控制協議,傳輸效率低,可靠性強,用于傳輸可靠性要求高,數據量大的數據),UDP(用戶數據報協議,與TCP特性恰恰相反,用于傳輸可靠性要求不高,數據量小的數據)。主要是將從下層接受的數據進行分段傳輸,到達目的地址后再進行重組。通常把這一層數據叫做段。
例:(有兩個協議TCP/UDP,保證數據正確送達)
會話層:通過傳輸層(端口號:傳輸端口與接受端口)建立數據傳輸的通路。主要在你的系統之間發起會話或者接受會話請求(設備之間需要互相認識可以是IP也可以是MAC或者是主機名)。
例:(怎么接收你發來的數據,需要建立網絡會話,對二進制數據解析,可以認為兩個交流的協議,設定一個協議例如HTTP)
表示層:可確保一個系統的應用層所發送的信息可以被另外一個系統的應用層讀取。
例:表示層(解析完數據需要表示,是文字還是圖片視頻)
應用層:最靠近用戶的OSI層。這一層為用戶的應用程序(例如電子郵件、文件傳輸和終端仿真)提供網絡服務
例:應用層(表示完展示在UI界面上)
HTTP
在HTTP/1.1協議中,定義了8種發送http請求的方法
GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
HTTP超文本傳輸協議,是短連接,是客戶端主動發送請求,服務器做出響應,服務器響應之后,鏈接斷開。
HTTP是一個屬于應用層面向對象的協議,HTTP有兩類報文:請求報文和響應報文。
HTTP請求報文:一個HTTP請求報文由請求行、請求頭部、空行和請求數據4部分組成。
HTTP響應報文:由三部分組成:狀態行、消息報頭、響應正文。?
HTTPS:安全超文本傳輸協議(Secure Hypertext Transfer Protocol),它是一個安全通信通道,基于HTTP開發,用于客戶計算機和服務器之間交換信息,使用安全套結字層(SSI)進行信息交換,即HTTP的安全版。
Scoket連接和HTTP連接的區別
HTTP協議是基于TCP連接的,是應用層協議,主要解決如何包裝數據。Socket是對TCP/IP協議的封裝,Socket本身并不是協議,而是一個調用接口(API),通過Socket,我們才能使用TCP/IP協議。
HTTP連接:短連接,客戶端向服務器發送一次請求,服務器響應后連接斷開,節省資源。服務器不能主動給客戶端響應(除非采用HTTP長連接技術),iPhone主要使用類NSURLConnection。
Socket連接:長連接,客戶端跟服務器端直接使用Socket進行連接,沒有規定連接后斷開,因此客戶端和服務器段保持連接通道,雙方可以主動發送數據,一般多用于游戲.Socket默認連接超時時間是30秒,默認大小是8K(理解為一個數據包大小)。
HTTP:一般用于非實時連接的請求,只有客戶端主動向服務器發送請求時,服務器才能返回數據給客戶端。
XMPP:基于xml通訊的協議,基于TCP發送xml數據,一般用于即時通信。?
GET和POST的區別:
GET請求:參數在地址后拼接,沒有請求數據,不安全(因為所有參數都拼接在地址后面),不適合傳輸大量數據(長度有限制,為1024個字節)。
GET提交、請求的數據會附在URL之后,即把數據放置在HTTP協議頭中。
以?分割URL和傳輸數據,多個參數用&連接。如果數據是英文字母或數字,原樣發送,
如果是空格,轉換為+,如果是中文/其他字符,則直接把字符串用BASE64加密。
POST請求:參數在請求數據區放著,相對GET請求更安全,并且數據大小沒有限制。把提交的數據放置在HTTP包的包體中.
GET提交的數據會在地址欄顯示出來,而POST提交,地址欄不會改變。
傳輸數據的大小:
GET提交時,傳輸數據就會受到URL長度限制(1KB),POST由于不是通過URL傳值,理論上不受限。
安全性:
POST的安全性要比GET的安全性高;
通過GET提交數據,用戶名和密碼將明文出現在URL上,比如登陸界面有可能被瀏覽器緩存
參考資料:https://objccn.io/issue-10-6/
SocketDemo:https://github.com/TeeMoYan/TMSocketDemo.git