網路遊戲資料傳輸:粘包的處理
所謂協議,說簡單點就是伺服器端和客戶端的一個約定,
比如,向伺服器傳送(1,0,1,“賬號:*** 密碼***”)
約定type中1代表登入模組,因為登陸不需要經過area協議,所以跳過area協議,直接到command協議,
command中1代表登陸,2代表註冊,3代表返回登陸結果,傳入的是1,故進行登陸邏輯,注意,如果type不是1,此處1,2,3就會代表別的東西了。
如果登陸成功,伺服器會返回(1,0,3,“true”)
如果不嫌麻煩,完全可以只定義一個協議,但是估計沒人那麼做
在傳輸過程中,為了進行高效的傳輸,所有的資料都會連在一起,如果傳的是int a = 1 string b = “qaz”傳輸時會變成1qaz
為了進行區分,通常會在傳輸資料體前用一個8位元組的int傳入這個資料體的長度(一般一個int就佔8個位元組),這個int通常叫做資料頭
如果想傳的資料佔256個位元組,那麼傳的時候會傳送256+8個位元組
如果想傳送一個float和一個bool,那麼真正傳送的會是連在一起的int float int bool
下面說下如何進行解析
在連線伺服器後,用BeginReceive進行資料接收,其中一個引數定義了快取大小
建立一個位元組陣列byte[1024]來作為快取
建立一個ByteArray來儲存待處理資料,ByteArray是可以改變大小的
當快取中收到資料時,會將資料加入到ByteArray
之後,判斷是否正在進行資料處理,如果沒在則開始資料處理:
↓
判斷ByteArray長度是否大於8,即是否把記錄訊息體長度的int讀取完
若小於8,不做處理等待,下次接受
若大於8,使用ReadInt讀取Int
ByteArray有一個position屬性,預設為0,當執行readint時會從0下標讀到8下標,因為int位元組長度為8,所以就算ByteArray裡有很多資料,就算有1024個位元組,readint也只會讀8位,之後position=8
舉個例子,如果傳入 1,2,3三個int 連續執行3次ReadInt就會得到1,2,3
獲取資料體長度int L後,再判斷剩下的資料長度是否大於L,若大於則說明資料完整,建立新的ArrayList2,從ArrayList讀取8到8+L的內容,AL的position+L
對ArrayList2進行Read,至於是ReadInt還是ReadBytes,要按照協議進行,簡而言之,伺服器傳的順序要和收的順序一致
之後,我們建立一個新的快取來儲存ListArray position之後的資料,再使ArrayList=這個新快取
再次執行"↓"之後的內容
相關程式碼:
//訊息體長度為一個8位元組數值 長度不足的時候 說明訊息未接收完成 或者是廢棄訊息
if (ioBuff.Length < 8) {
isRead = false;
return;
}
//讀取定義的訊息的長度
int dataSize = ioBuff.ReadInt();
if (dataSize > ioBuff.Length - 8) {
//訊息體長度不夠 等待下個訊息的到來
ioBuff.Postion = 0;
isRead = false;
return;
}
//建立完整訊息體的動態陣列
ByteArray ioData = new ByteArray();
//從訊息快取中取出正確的訊息體 位元組陣列內容
ioData.WriteBytes(ioBuff.Buffer, 8, dataSize);
ioBuff.Postion += dataSize;
int type=ioData.ReadInt();
int area=ioData.ReadInt();
int command=ioData.ReadInt();
byte[] cache=ioData.ReadBytes();
object message = AceCode.Code.aceDecode(cache);
//轉換為傳輸模型用於使用
SocketModel model = new SocketModel(type, area, command, message);
//將訊息儲存進訊息列表 等待Unity來讀取
messageList.Add(model);
////
//建立新快取區
ByteArray bytes = new ByteArray();
//將舊快取區的剩餘資料移動到新快取區
bytes.WriteBytes(ioBuff.Buffer, ioBuff.Postion, ioBuff.Buffer.Length - ioBuff.Postion);
//更新快取區
ioBuff = bytes;
onData();
相關文章
- 資料接收中粘包及半包的處理
- C# 優雅的處理TCP資料(心跳,超時,粘包斷包,SSL加密 ,資料處理等)C#TCP加密
- Netty Protobuf處理粘包分析Netty
- tcp中的粘包、半包的處理方法TCP
- go語言處理TCP拆包/粘包GoTCP
- Xamarin Essentials教程資料處理傳輸資料
- TCP通訊處理粘包詳解TCP
- 路由器網路中資料包傳輸分析路由器
- 即時通訊下資料粘包、斷包處理例項(基於CocoaAsyncSocket)
- GO語言手動處理TCP粘包GoTCP
- 網路傳輸時間以及Client的處理的測試方案client
- [ gev ] Go 語言優雅處理 TCP “粘包”GoTCP
- Jmeter中使用前置處理器加密傳輸資料JMeter加密
- 利用實體bean物件批量資料傳輸處理Bean物件
- 網路傳輸時間和客戶端處理時間的界定(批處理應用)客戶端
- 資料線線損和長度對資料傳輸和網路傳輸的影響
- 資料包遠端傳輸的抓包系統scratch
- 使用EXPDP IMPDP傳輸不同資料庫的不同表空間(新增網路傳輸)資料庫
- 網路中的資料傳輸模式有哪些-鐳速模式
- 體會KEIL5資料處理和傳輸過程
- 計算機網路 - TCP粘包、拆包以及解決方案計算機網路TCP
- Oracle 12C 跨網路傳輸資料庫Oracle資料庫
- 依賴反向傳播改進神經網路資料處理的精確度反向傳播神經網路
- 資料泵匯出資料包錯處理
- TransData for Mac - 網路資料傳輸速率監測軟體Mac
- 網路資料傳輸速率監測軟體:TransData for MacMac
- 技術筆記(12)網路資料傳輸問題筆記
- 不安全網路中的資料安全傳輸利器——GnuPG(上)
- php傳送超大資料處理PHP大資料
- 硬核圖解TCP粘包 資料包:我只是犯了每個資料包都會犯的錯圖解TCP
- 網路傳輸協議協議
- Python 網路資料傳輸協議 TCP 程式設計Python協議TCP程式設計
- 網路中的圖片傳輸
- socket網路傳輸的問題
- Python 基於Twisted框架的資料夾網路傳輸原始碼Python框架原始碼
- 網路資料原來是這麼傳輸的(結合動畫解析)動畫
- 網路傳輸時間和客戶端處理時間的界定(互動式應用)客戶端
- TCP 粘包拆包TCP