怎樣把一個Json字符串傳輸到網絡的另一端?
1. 確定傳輸協議:
我們在進行網絡編程的時候,首先要確定的就是傳輸協議,常見的傳輸協議就是UDP和TCP。
我採用的是TCP,因爲,TCP可以保證傳輸數據的可靠性。
2. 應用層協議。
爲啥應用層還要定義一次協議呢?
因爲,應用層都是面向對象的編程,而傳輸層面向的是二進制的數據流,所以,我們要定義協議完成數據對象與二進制數據流直接的轉換。
當然,通常來說,傳輸Json串,有兩種方案可以實現:
A. 以換行符作爲分隔符傳輸Json串,換句話說,就是在每個Json串後面追加一個換行符進行數據傳輸。這樣的話,接收端在接收數據的時候,發現換行符,就意味着一個Json串接收完畢了。
B. 採用添加包頭(或者包頭+包尾)的方式傳輸Json串,包頭中可以保存Json串的一些有關傳輸的信息,包尾可以添加分隔符(可以不添加包尾數據)。
我們知道,Java語言是要先定義類然後才能創建對應的對象的,如果Json串被接收之後,如果想要反序列化成爲Java對象,只有兩種方案:一種是使用Map存放Json的屬性信息,另一種是自定義Class與Json對應,然後反序列化得到對象。這第二種方案裏面,有一個關鍵的內容是,我們要先知道Json與Class的映射關係才能將Json反序列化成對象,很顯然,上面說的A用換行符傳輸Json串就不適用了,因爲,這種方式中,我們無法拿到Json與Class的映射關係(當然,如果Json串裏面包含這種關係,是沒有什麼問題的,我們談論的思想是想盡量將Json與傳輸本身分離開來)。
下面,我們做一下小結:
方案A傳輸Json可以將Json映射成Map對象進行數據的訪問;
方案B傳輸Json可以在包頭中定義Class的編號,接收端通過編號找到對應Class類,反序列化成對象進行數據訪問。
我打算使用後者寫一個Demo。
3. BIO還是NIO
BIO雖然編程模型較爲簡單,但是,這種IO的操作方式,早已淡出了我的視線,IO密集型的程序,BIO會使得大量的線程處於阻塞狀態,這對於我這種強迫症患者來講,是不可容忍的。我的理念裏面,多線程的最佳使用場景是運用在CPU密集型的程序當中。所以,爲了讓一條線程能夠管理更多的連接,進行更多的IO操作,我還是選擇的NIO(當然,還有一個原因是因爲NIO有框架可以簡化編程)。
4. 選擇框架,毫無疑問,衆所周知,SpringBoot + Netty 。
5. 聊一下協議中的數據格式:
頭部:4bytes | 2bytes | 2bytes | 2bytes | 2bytes
0xFFFE0608 | Version | Channel | Command | Length
開始分隔符 | 協議版本 | 頻道號 | 命令字(類ID)| 包體長度
包體:Xbytes
長度與包頭部分定義的長度一致,採用UTF-8編碼進行轉換
包尾:4bytes
0xFFFE0806
結尾分隔符
其中,包尾可以不使用的,我這裏添加包尾,是想在接收端遇到碎包時,可以通過包尾分隔符跳過碎包的數據,或者爲接收端提供另只用解析報文的方式。這種情況在Demo中並沒有進行實現,所以,包尾部分,屬於備選信息。