最近在利用Html5的WebSocket進行即時通訊,一點小心得,大家一起討論吧
首先把WebSocket的協議網址和WebSocket API網址給大家:
協議:http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#page-30
API:http://www.w3.org/TR/2012/CR-websockets-20120920/#dom-websocket-send
首先要了解一下WebSocket的原理:
上圖表示的是已經建立WS連接的WebSocket通信。如圖可見單純從服務器端來講,WS的服務器端實際上就一個傳統Socket通信,假如你要模擬即時通訊,那就把文本轉換為二進制流;假如傳輸圖像,就把Blob轉換為二進制流;假如傳輸數值型數組就把數組轉換為字節數組。本研究中是實現大規模地形數據的傳輸,地形網格其本質就一個n*n的矩形數組,根據博文http://www.cnblogs.com/fengyunlishi/archive/2013/05/09/3070142.html,可以曉得。顯然把地形數據轉換成文本字符串是極為不合理的(因為這不僅僅涉及到文本壓縮,還要考慮客戶端還要把文本數據再處理成數值數組哦)。
對於大規模數據的傳輸,有兩種方案:
(1)將整型數組根據某個分隔符連接成字符串,之后將字符串轉換為字節數組,但是要記住哦:分隔符的數量幾乎與整型數組長度相等哦,最終數據量變成了原來的2倍大小。
(2)將整型數組直接轉換為字節數組,一個Int16型的整數無論大小,轉換為字節數組后,長度為一常量:2,易於編程實現。
意義太明顯,哈哈,所以本文采用將數值型數組轉換為字節數組。
代碼如下:
UInt16[] int16Array = new UInt16[3] { 0, 258, 1 };
MemoryStream int16mem = new MemoryStream();
BinaryWriter int16byteWR = new BinaryWriter(int16mem);
foreach (Int16 hehe in int16Array)
{
int16byteWR.Write(hehe);
}
Byte[] _content = int16mem.ToArray();………… 略
關鍵點一:你如何決定WS服務器端傳輸什么類型的數據呢?
通過WebSocket的數據幀結構圖(網上有很多介紹WebSocket數據幀結構的博客),可以了解WebSocket的數據傳輸格式是在Opcode位中設計的:
Opcode:4bit,定義有效負載數據,如果收到了一個未知的操作碼,連接也必須斷掉,以下是定義的操作碼:
x0表示連續消息片斷
x1表示文本消息片斷//表示傳輸文本型數據
x2表未二進制消息片斷//表示傳輸Blob以及二進制數據
x3-7為將來非控制消息片斷保留地操作碼
x8表示連接關閉
x9表示心跳檢查的ping
xA表示心跳檢查的pong
xB-F為將來控制消息片斷的保留地操作碼
本文把Opcode設置為x2.
關鍵點二:
第二個關鍵在於WebSocket的js客戶端接收,代碼如下:
var ws; ws = new WebSocket("ws://localhost:8989/test");
ws.onopen = WSonOpen; ws.onmessage = WSonMessage;
ws.onclose = WSonClose; ws.onerror = WSonError;……
function WSonOpen() {
ws.binaryType = 'arraybuffer';//可將 WebSocket 對象的 binaryType 屬性設為“blob”或“arraybuffer”。默認格式為“blob”(您不必在發送時校正 binaryType 參數)。
};
function WSonMessage(event) {
var result = new Int16Array(event.data);
for (var i = 0; i < result.length; i++) {
alert(result [i]);
}
};
OK了,大功告成,程序中result就是傳過來的數值型數組。