最近在整理通信層相關知識,這篇文章是邊整理邊寫的,有些地方可能不夠准確,還請各位路過的大牛專家指出來。這次整理的socket通信是基於TCP的,實現方式是GCD形式,以下記錄的都是些理論知識,方便自己回憶。
1、socket通信原理:現網絡上有很多socket開園框架文件,基本上能滿足簡單網絡通信,但如過你的項目需要成熟的網絡通信,還需要自 己對socket好好研究完善下。socket通信分為server端和client端,開發過程中分別對應着服務器和客戶端。當連接上服務器 后,socket就會啟動一個while或for無限循環,不斷的異步監聽socket動靜,看是否有read或者write動作,直到出錯或者主動結 束。
socket通信傳輸的都是字節流,傳輸時沒有包的概念的。至於我們經常說的包的概念,是我們制定了一定的規則形成的。常用規則有兩種,一 種是制定特定的分隔符(delimiter)來分割每個包,此時必須保證每條信息體中不包含該分隔符。第二種是指定每條消息體的長度,比如,在每條消息體 之前插入一個4字節長度的無符號整形來表明后面的消息體長度(一般包體長度限制在8k大小內,遇到消息體過大的信息時,一般采用分包發送和拼包解析)。其 中第二種方式更常見一些。
基於TCP鏈接的socket通信中,經常會涉及粘包、分包、解包的問題,一下久這問題簡單說一下。
粘包:使用TCP長連接就會引入粘包的問題,粘包是指發送方發送的若干包數據到接收方接收時粘成一包,從接收緩沖區看,后一包數據的頭緊接 着前一包數據 的尾。粘包可能由發送方造成,也可能由接收方造成。TCP為提高傳輸效率,發送方往往要收集到足夠多的數據后才發送一包數據,造成多個數據包的粘連。如果 接收進程不及時接收數據,已收到的數據就放在系統接收緩沖區,用戶進程讀取數據時就可能同時讀到多個數據包。
粘包一般的解決辦法是制定通訊協議,由協議來規定如何分包解包。
分包:常用分包的邏輯是先發一個長度,然后緊接着是數據包內容,這樣就可以把每個包分開。
解包:由於我們應用層數據包既可以傳命令也可以傳數據,因而針對每個包我們進行解包,分出命令和數據分別處理,因而每個Socket服務對象都需要解包。解包過程中,才會出現我們常見的包頭、信息體長度、信息體。
粘包、分包、解包解決方案:東家DZH:采用的是用一個足夠大(500*1024)的接受緩存pRecvBuf去讀區socket(recv()),然后使用君子協定讓數據報的開頭都是一個標准的包頭信息,包頭信息中包含着本包的包體長度,利用這個包體長度曲讀取本包數據包體。讀完后,如果該數據包還有未讀數據,則重復上訴解包操作。直到完成。
東家EM:每次收到數據報時,先讀取前4個字節轉為無符號整形作為本消息包的長度length,然后一直重socket中read,直到讀取length長度為之。這樣可以解決分包發送問題,也可以解決粘包問題。