在silverlight中利用socket傳送圖片或檔案

lcc發表於2021-09-09

silverlight中的socket通訊支援,讓sl開發基於web的聊天工具成為了可能,後來OpenFileDialog,SaveFileDialog的出現,更使得邊聊天邊傳送圖片(檔案)得以實現,最新的SL4中又加入了攝像頭支援,也許不久真的可以用silverlight開發出功能強大的影片聊天系統,目前唯一還沒有解決的是p2p問題,根據sl3的sdk文件所述: 

 

Socket 類為網路通訊提供了一組方法和屬性。Socket 類允許您使用 ProtocolType 列舉中所列出的任何一種通訊協議執行非同步資料傳輸。當前,Silverlight 上唯一支援的 ProtocolType 是 TCP 協議 (Tcp)。

關於在 Silverlight 中使用套接字的一個限制是:網路應用程式可以連線到的埠範圍必須在 4502-4534 範圍內。這些是使用套接字從 Silverlight 應用程式進行連線所唯一允許使用的埠。如果連線的目標埠不在此埠範圍內,則嘗試連線時將會失敗。 

 

silverlight中的socket使用的協議目前只有tcp協議,不知道以後會不會增加其它協議。


廢話不多說,關於silverlight的socket原理及流程,請參看我部落格轉貼的【csdn周飛的文章】,其大致流程我畫了張圖:

圖片描述 

 

簡單點說,我們需要處理三方面的東西:

1.服務端上的策略請求監聽(943埠):用於接受silverlight socket客戶端首次連線時自動發起的策略請求
2.服務端上的訊息資料監聽(4502至4534範圍中的某一個埠):用於接受socket客戶端傳送過來的使用者資料,並根據實際需要轉發(或不處理)
3.silverlight客戶端的服務端連線,向服務端發資料,非同步接受服務端資料...等

 

園子裡webabcd為我們寫了一個很不錯的socket聊天室demo,我在他的基礎上,增加了圖片傳送及檔案傳送的演示。注:僅僅是演示,圖片解碼時還有一些問題,尚無法用於正式應用。以下是執行截圖:

圖片描述 

 

要點:

1.如何判斷髮過來的資料(byte陣列),是文字還是圖片?或是檔案?
我用了一個比較原始的辦法,在byte陣列中前後加入了一些特定字元,類似字串的分隔符,接收完以後,再根據特定字元拆分,然後根據其中的標記位(開發人員可自定義)來確定格式。

2.傳送時,檔案或圖片如何轉化為byte陣列?
OpenFileDialog可以將選擇後的檔案返回一個流,再利用BinaryReader將檔案流轉化為陣列

3.接受時,如何將byte陣列還原為檔案(或圖片),並儲存?
利用MemoryStream.write將byte陣列變成流,然後再呼叫bitmap.SetSource設定源,從而得到圖片;至於檔案儲存,SaveFileDialog確定儲存的檔名後,也會返回一個流,將接受到的byte陣列轉化為流,然後儲存即可

4.傳送的資料如果超過緩衝區大小,一次不能接受完整如何處理?

傳送時,前後加上特定字元做為標記位,第一個接收到的字元為特定字元則認為是資料包的開始,如果最後一個字元不是特定字元,說明未接收完整,則繼續迴圈接收,直到最後一個字元遇到特定字元為止。

問題:
圖片或檔案透過流轉化為byte陣列後,如果陣列本身就包含分隔字元,會導致收到資料後“解碼”失敗,所以在傳送前,我把圖片或檔案陣列中的分隔符替換成其它字元了,但這樣會導致還原時圖片失真。(2009-11-30更新:關於這個問題的解決辦法,事後想了下,問題的出現是由於分隔符重複引起的,可以換一種思路,比如在byte前端明確標註該資料包的長度,類似 ^512^...後面是傳送的內容(這裡的內容可以是自己定義的複雜物件,利用序列化最終轉化為byte[]),這樣接受到第一個"^"時認為是開始,第一個與第二個"^"之間的數字即為後面內容流的長度,理論上應該可行)


除錯方法:
1.先啟動解決方案中的Server
2.再啟動silverlight專案Client
3.測試圖片或檔案傳送時,我在原始碼根目錄下特意放了一張小圖片(test.png)及一個小檔案檔案(test.txt),方便大家除錯。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2331/viewspace-2801069/,如需轉載,請註明出處,否則將追究法律責任。

相關文章