1.粘包
目前sl中的socket只能用tcp/ip協議,而tcp/ip本質是一個"流"協議,也就是說資料無邊界,發送的就是一連串的位元組(沒有資料包的概念),因此連續發送時有所謂的“粘包”現象,詳細解釋如下:
比如你設定發送緩衝區的大小是512位元組,如果(在相隔時間極短的情況下)連續發送次資料,第一次為500位元組,第二次為100位元組,實際上你在伺服器端接收到的二次資料長度並不是500和100,而是512和88.
換言之:如果socket能“感覺”到馬上還有資料要發送,而且在本次發送的緩衝區還有空餘時,它會自動把下次發送的內容挪一部分過來,直到本次緩衝區填滿,以便有效利用緩衝區,減少發送次數,至於它是如何感覺的,我就不知道鳥:)
所以如果想正確的劃清資料邊界,得自己想辦法封包/拆包
常見的解決辦法:在發送方與接收方制定一個共同的約定,比如定義一個結構體struct,把“包長度,包序號,要發送的資料,包的唯一標識...”這一堆東西封裝在struct中,然後通過序列化最終得到一個byte[]進行發送。
另外如果最終得到的byte[]太大,超過了資料下標所允許的最大值(比如傳遞大檔案時),會導致接收時還原序列化失敗,所以還得人工把大塊頭資料割成一塊一塊,這裡有一個技巧:為了避免前面提到“scoket自我感覺良好”進行的資料挪移,分割的單位建議正好就是緩衝區的大小,如果不足一個緩衝區,寧可湊數填寫一些空位元組也要湊滿一個緩衝區長度--這樣系統會覺得你在高效使用緩衝區,沒有浪費,也就不會管閑事了
2.異常捕獲
網路編程中,會有各種不可控的情況,所以異常的捕獲很重要,否則程式會用著用著就掛掉了。
3.異常資料包的及時清理
異常資料包指“非法的”或“不完整的(比如一個大檔案最終拆分成10個包,結果第10個包都收到了,前面的某個包即始終收不到)”資料包,對於這類資料包,要及時清理否則會一直佔用資源(必要時可以將串連關閉)
後話:很期待silverlight在未來的版本中,加入udp協議支援,這樣應用範圍將更加廣泛。