聊一聊客戶端項目內應用Socket碰到的狀況

本題不講基礎,講的是實際應用。首先項目內採起Socket,想必都是從 長鏈接 頻繁數據通信出發,但大多數人使用的時候都是採用了堵塞方式去建立Socket,堵塞方式:每產生一個鏈接,服務端就要開啓一個線程來處理,沒處理完成不能退出,客戶端會一直在等待結果返回, 非堵塞方式:基於反應器模式,多路併發,多路複用,事件來了就處理,處理完成就歸還,相信對線程熟悉的老哥們這時候確定會想到了用線程池管理,沒錯,這就是非堵塞的優點之處。緩存

舉個例子

當前有100個客戶端鏈接服務端,堵塞方式:就要打開100個線程來處理,不能重複回收複用,由於你要服務完你接待的上帝(客戶端)才能夠結束 非堵塞方式:只須要開30個線程,經過線程池管理,處理完成事件回收、複用 咳咳咳,看到這裏你們應該明白這兩種模式的好壞取捨了,固然,這對於客戶端來講是看不到的,主體說的是服務端的性能了,有點跑題了!!併發

正式進入正文:

咱們用Socket就是長連接頻繁數據通信,居然有通信,那麼就離不開數據交互。不知道各位大大有沒有接收過超過1024字節的數據呢?如一張動態圖片、文件之類。 若是有,那麼應該能猜想到小二我準備說的主題了,沒有接收過的同窗,請注意認真聽講了喂!!!框架

場景:服務端向客戶端發送一張8M動態圖片,客戶端輪詢讀取接收,接收到通知UI出列刷新,聽起來流程一點問題沒有是否是? no!no!no! 同窗,要是這樣簡單我就對不起鋪墊了,服務端確實是整個圖片發出去了,可是因爲字節多大,通信框架處於好心,主動幫咱們把8M 的數據字節流拆成了N多個包發送給客戶端,so 前面客戶端接收到的只是某一個包,而不是完整的8M動態圖性能

如圖

前面過於純潔的同窗下課後來自覺來我這裏領下做業!!! 言歸正傳,數據過大,被強行分包?那麼咱們要怎麼處理呢?

聰明的童鞋可能想到了,那咱們本身來分包處理,這樣就不會處於被動了.這裏又引起一個問題。 怎麼分包?分幾個包?客戶端怎麼知道那幾個包組合起來是一個完整的包? 分包:咱們先把數據轉成字節流,在轉成進制字符串,在進行字符串拆分便可線程

分幾個包:一般客戶端在讀取的時候都會設置一個長度(readLine獲取)因此這裏咱們也不用過於糾結,服務端1024字節或者其餘來拆分均可以。3d

客戶端怎麼接收?

假設服務端把8m動態圖分紅了8個數據包下發?客戶端接收後怎麼判斷是否完整包?cdn

來,各位看官發揮一下想象力-_-blog

想想咱們轉成了進制字符串,那咱們可不能夠在上面作一下手腳處理呢? 答案固然是 能夠的啦!!隊列

咱們能夠在沒拆分前的進制字符串頭和尾添加標識字符,例如:進制字符串是 88777222777 ,咱們用AA來看成標識字符:AA88777222777AA。 這樣看起來客戶端是否是很明確的知道怎麼去處理了呢?事件

客戶端只要接受收據,碰到AA做爲開頭的數據包,就緩存起來放進隊列或者本身的緩衝變量,等到碰見AA結尾的數據包,就總體拼接,剔除開頭結尾的AA,這樣不就是一個完整的數據包了麼? ps:這裏還有一個小問題, 有時候通信頻繁的時候一些不可知因素還容易產生數據缺失,因此咱們上面的方法還有一點缺陷,咱們不知道字節數對不對。 想一想看,咱們都能在沒拆分前的進制字符加上AA標識,爲何不能把長度也加上去呢?

如圖

如上圖所示,咱們能夠和客戶端約定好數據協議,這裏有沒有寫過串口的童鞋呢?那麼接觸起來沒有絲毫困難! 起始位+數據包長度+數據+結束位,這裏的數據處理都是用進制字符哦,咱們能夠這樣設置 起始位 2個字節+數據包長度 1個字節+數據 n個字節+結束位 2個字節,不熟悉字節和進制的童鞋,你要好好補一補基礎了。 如上流程,那麼客戶端在拿到一個開頭結尾都是AA的完整數據包以後,在取出第三個字節的數據包長度,判斷一下數據包就可知道是否完整了 最後~ 狀況固然不會那麼少了,還有

粘包

斷包

等等呢,小二今天還有事情,下次有時間在和各位大大具體分析了,by~

相關文章
相關標籤/搜索