WebSocket 規範

WebScoket 規範

4.1 握手協議

websocket 是 獨立的基於TCP的協議, 其跟http協議的關係僅僅是 WebSocket 的握手被http 服務器當做 Upgrade request http包處理。 websocket 有自己的握手處理。 TCP連接建立後,client 發送websocket 握手請求. 請求包需求如下:

  • 必須是有效的http request 格式
  • HTTP request method 必須是GET,協議應不小於1.1 如: Get /chat HTTP/1.1
  • 必須包括Upgrade 頭域,並且其值爲“websocket”
  • 必須包括"Connection" 頭域,並且其值爲 "Upgrade"
  • 必須包括"Sec-WebSocket-Key"頭域,其值採用base64編碼的隨機16字節長的字符序列, 服務器端根據該域來判斷client 確實是websocket請求而不是冒充的,如http。響應方式是,首先要獲取到請求頭中的Sec-WebSocket-Key的值,再把這一段GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"加到獲取到的Sec-WebSocket-Key的值的後面,然後拿這個字符串做SHA-1 hash計算,然後再把得到的結果通過base64加密,就得到了返回給客戶端的Sec-WebSocket-Accept的http響應頭的值。
  • 如果請求來自瀏覽器客戶端,還必須包括Origin頭域 。 該頭域用於防止未授權的跨域腳本攻擊,服務器可以從Origin決定是否接受該WebSocket連接。
  • 必須包括"Sec-webSocket-Version" 頭域,當前值必須是13.
  • 可能包括"Sec-WebSocket-Protocol",表示client(應用程序)支持的協議列表,server選擇一個或者沒有可接受的協議響應之。
  • 可能包括"Sec-WebSocket-Extensions", 協議擴展, 某類協議可能支持多個擴展,通過它可以實現協議增強
  • 可能包括任意其他域,如cookie

示例如下:

        GET /chat HTTP/1.1
        Host: server.example.com
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
        Origin: http://example.com
        Sec-WebSocket-Protocol: chat, superchat
        Sec-WebSocket-Version: 13

Server 接手到握手請求後應處理該請求包括:

  • 處理請求包括處理GET 方法
  • 驗證Upgrader頭域
  • 驗證Connection 頭域
  • 處理Sec-WebSocket-Key頭域,方法見上;
  • 處理Sec-WebSocket-Version
  • 處理Origin頭域,可選, 瀏覽器必須發送該頭域
  • 處理Sec-WebSocket-Protocol頭域,可選
  • 處理Sec-WebSocket-Extensions 頭域,可選
  • 處理其他頭域,可選
  • Server 發送握手響應,這裏只介紹服務器接受該連接情況下,包括:
  • http Status-Line
  • Upgrade 頭域 ,值必須是"websocket"
  • Conntion頭域,值必須是:“Upgrade”
  • Sec-WebSocket-Accept” 頭域,該頭域的值即處理Sec-WebSocket-Key" 域後的結果。
  • 可選的"Sec-WebSocket-Protocol"頭域
  • 可選的"Sec-WebSocket-Extensions"頭域

響應可能如下:

        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat

4.2 數據傳輸

該節主要參考了 http://blog.csdn.net/fenglibing/article/details/6852497。  在WebSocket 協議中,使用序列frames方式來傳輸數據。一個frame的標準格式如下:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

FIN:1位,是否是消息的結束幀(分片)

RSV1, RSV2, RSV3: 分別都是1位, 預留,用於約定自定義協議。 如果雙方之間沒有約定自定義協議,那麼這幾位的值都必須爲0,否則必須斷掉WebSocket連接;

Opcode:4位操作碼,定義有效負載數據,如果收到了一個未知的操作碼,連接也必須斷掉,以下是定義的操作碼:

%x0 表示連續消息分片
%x1 表示文本消息分片

%x2 表未二進制消息分片

%x3-7 爲將來的非控制消息片斷保留的操作碼

%x8 表示連接關閉  %x9 表示心跳檢查的ping

%xA 表示心跳檢查的pong

%xB-F 爲將來的控制消息片斷的保留操作碼

Mask: 定義傳輸的數據是否有加掩碼,如果設置爲1,掩碼鍵必須放在masking-key區域,客戶端發送給服務端的所有消息,此位的值都是1;

Payload length: 傳輸數據的長度,以字節的形式表示:7位、7+16位、或者7+64位。如果這個值以字節表示是0-125這個範圍,那這個值就表示傳輸數據的長度;如果這個值是126,則隨後的兩個字節表示的是一個16進制無符號數,用來表示傳輸數據的長度;如果這個值是127,則隨後的是8個字節表示的一個64位無符合數,這個數用來表示傳輸數據的長度。多字節長度的數量是以網絡字節的順序表示。負載數據的長度爲擴展數據及應用數據之和,擴展數據的長度可能爲0,因而此時負載數據的長度就爲應用數據的長度。注意Payload length不包括Masking-key在內。

Masking-key: 0或4個字節,客戶端發送給服務端的數據,都是通過內嵌的一個32位值作爲掩碼的;掩碼鍵只有在掩碼位設置爲1的時候存在。 數據Mask方法是,第 i byte 數據 = orig-data ^ (i % 4) .

Payload data: (x+y)位,負載數據爲擴展數據及應用數據長度之和。

Extension data:x位,如果客戶端與服務端之間沒有特殊約定,那麼擴展數據的長度始終爲0,任何的擴展都必須指定擴展數據的長度,或者長度的計算方式,以及在握手時如何確定正確的握手方式。如果存在擴展數據,則擴展數據就會包括在負載數據的長度之內。

Application data:y位,任意的應用數據,放在擴展數據之後,應用數據的長度=負載數據的長度-擴展數據的長度。

把消息分片處理主要是處於以下兩個原因:

  • 消息接收方事先並不知道消息大小, 而且也沒必要預留一個足夠大的buffer來處理;
  • multiplexing

消息分片一些規則如下(不全):

  • 爲分片消息(single-frame) 其FIN置爲1,並且opcode code 不是 0;
  • 分片消息序列如下, 第一幀FIN置爲0,opcode code不是0; 接着是FIN置爲0,opcode code也是0; 最後幀 FIN爲1,opcode code爲0.
  • 在分片消息發送期間可能插入了控制幀
  • 控制幀不能分片

控制幀的opcode符號位爲1, 目前控制幀包括 0×8(Close), 0×9(Ping) 0xA (Pong). 0xB-0xF 被預留。

詳細解析如下,來自http://blog.csdn.net/fenglibing/article/details/6852497

   ws-frame                = frame-fin
                             frame-rsv1
                             frame-rsv2
                             frame-rsv3
                             frame-opcode
                             frame-masked
                             frame-payload-length
                             [ frame-masking-key ]
                             frame-payload-data
   frame-fin               = %x0 ; 表示這不是當前消息的最後一幀,後面還有消息
                           / %x1 ; 表示這是當前消息的最後一幀
   frame-rsv1              = %x0
                             ; 1 bit, 如果沒有擴展約定,該值必須爲0
   frame-rsv2              = %x0
                             ; 1 bit, 如果沒有擴展約定,該值必須爲0
   frame-rsv3              = %x0
                             ; 1 bit, 如果沒有擴展約定,該值必須爲0
   frame-opcode            = %x0 ; 表示這是一個連續幀消息
                           / %x1 ; 表示文本消息
                           / %x2 ; 表示二進制消息
                           / %x3-7 ; 保留
                           / %x8 ; 表示客戶端發起的關閉
                           / %x9 ; ping(用於心跳)
                           / %xA ; pong(用於心跳)
                           / %xB-F ; 保留
   frame-masked            = %x0 ; 數據幀沒有加掩碼,後面沒有掩碼key
                           / %x1 ; 數據幀加了掩碼,後面有掩碼key
   frame-payload-length    = %x00-7D
                           / %x7E frame-payload-length-16
                           / %x7F frame-payload-length-63
			   ; 表示數據幀的長度
   frame-payload-length-16 = %x0000-FFFF
			   ; 表示數據幀的長度
   frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
			   ; 表示數據幀的長度
   frame-masking-key       = 4( %0x00-FF ) ; 掩碼key,只有當掩碼位爲1時出現
   frame-payload-data      = (frame-masked-extension-data
                              frame-masked-application-data)  
                  ; 當掩碼位爲1時,這裏的數據爲帶掩碼的數據,擴展數據及應用數據都帶掩碼
                           / (frame-unmasked-extension-data
                              frame-unmasked-application-data) ;
                 當掩碼位爲0時,這裏的數據爲不帶掩碼的數據,擴展數據及應用數據都不帶掩碼

   frame-masked-extension-data     = *( %x00-FF ) ; 目前保留,以後定義
   frame-masked-application-data   = *( %x00-FF )
   frame-unmasked-extension-data   = *( %x00-FF ) ; 目前保留,以後定義
   frame-unmasked-application-data = *( %x00-FF )

 

Close 處理

Close 幀的opcode是0×8. 接收到 Close 幀後,如果之前沒發送過Close幀,則其必須發送Close 幀響應,但其可以延遲發送Close響應幀,例如在其發送完數據之後發送;但是,協議不保證對方在發送Close 幀後仍會處理其後續的數據。Close幀可能Client發起也可能是Server發起。

Ping-Pong 幀

接收到Ping幀後將響應Pong幀, 主要用於檢測網絡連接情況。

Extensions

WebSocket 支持協議擴展。 例如增加一個認證處理或者速率控制等,這通過client-server 協商完成。在WebSocket 握手處理時,通過頭域Sec-WebSocket-Extensions來完成協商。 例如:

Sec-WebSocket-Extensions: mux; max-channels=4; flow-control,
          deflate-stream

服務器接收一個或多個extensiions 通過再起響應的Sec-WebSocket-Extensions頭域增加一個或多個extension完成。

 

說明:

 

服務器建立成功之後,如果有客戶端請求連接本服務器,需要用socket_accept等方法建立一個新的socket連接,並接收客戶端的請求信息,處理之後,返回響應信息,然後握手成功。  

接下來是字符串通信,客戶端send過來一段字符串信息,服務器端接收到並返回給客戶端這個字符串。   首先我們處理接收到的信息,根據上篇文章介紹的數據傳輸格式,並firefox的FIN一直爲1,RSV1,2,3爲0,如果是文本消息,那麼opcode爲1,所以數據包的第一個數據是0x81,然後是一位mask值,firefox發來的數據是加了掩碼的,所以mask值爲1,後面跟7位是數據信息長度,我們以客戶端發送hi爲例,那麼長度就是2個字節,則第二個數據就是0x82,這裏沒有約定擴展數據,所以不存在擴展數據長度字節,接下來是4個數據的掩碼(因爲我們這裏是發送hi,2個字節的信息,小於125個字節,所以掩碼是第3-第6個數據,根據數據長度的不同,掩碼的位置也不同,如果取到那7位表示的值是126,則掩碼爲第5-第8個數據,如果取到那7位表示的值是127,則掩碼爲第11-第14個數據),後面跟客戶端發送的內容數據,處理接收到的數據我們需要用取到的掩碼依次輪流跟內容數據做異或(^)運算,第一個內容數據與第一個掩碼異或,第二個內容數據與第二個掩碼異或……第五個內容數據與第一個掩碼異或……以此類推,一直到結束,然後對內容進行編碼。

 

根據數據長度的不同,掩碼的位置也不同:

從第9個字節開始是 1111101=125,掩碼是第3-第6個數據

從第9個字節開始是 1111110=126,掩碼是第5-第8個數據

從第9個字節開始是 1111111=126,掩碼是第11-第14個數據

 

舉例一:

複製代碼
 1 hi
 2 1000000110000010 1101011011101001
 3 111110 111000 10111110 10000000
 4 111110 111001 11010110 11101001
 5                1101000  1101001
 6                
 7         [0]    129    byte
 8         [1]    130    byte
 9         [2]    214    byte
10         [3]    233    byte
11         [4]    62     byte
12         [5]    56     byte
13         [6]    190     byte
14         [7]    128     byte
15 
16 
17 1234567890                 
18         [0]    129    byte
19         [1]    138    byte
20         
21         [2]    108    byte
22         [3]    255    byte
23         [4]    86    byte
24         [5]    166    byte
25         
26         [6]    93    byte
27         [7]    205    byte
28         [8]    101    byte
29         [9]    146    byte
30         [10]    89    byte
31         [11]    201    byte
32         [12]    97    byte
33         [13]    158    byte
34         [14]    85    byte
35         [15]    207    byte
複製代碼


 舉例二:

 

複製代碼
  1 01234567890123456789012345678901234567890123456789
  2 01234567890123456789012345678901234567890123456789
  3 01234567890123456789012345678901234567890123456789
  4 01234567890123456789012345678901234567890123456789
  5 
  6 01234567890123456789012345678901
  7 10000001111111100110010011001101
  8 
  9         [0]    129    byte
 10         [1]    254    byte
 11         [2]    0    byte
 12         [3]    201    byte
 13         
 14         [4]    77    byte
 15         [5]    175    byte
 16         [6]    124    byte
 17         [7]    107    byte
 18         
 19         [8]    125    byte
 20         [9]    158    byte
 21         [10]    78    byte
 22         [11]    88    byte
 23         [12]    121    byte
 24         [13]    154    byte
 25         [14]    74    byte
 26         [15]    92    byte
 27         [16]    117    byte
 28         [17]    150    byte
 29         [18]    76    byte
 30         [19]    90    byte
 31         [20]    127    byte
 32         [21]    156    byte
 33         [22]    72    byte
 34         [23]    94    byte
 35         [24]    123    byte
 36         [25]    152    byte
 37         [26]    68    byte
 38         [27]    82    byte
 39         [28]    125    byte
 40         [29]    158    byte
 41         [30]    78    byte
 42         [31]    88    byte
 43         [32]    121    byte
 44         [33]    154    byte
 45         [34]    74    byte
 46         [35]    92    byte
 47         [36]    117    byte
 48         [37]    150    byte
 49         [38]    76    byte
 50         [39]    90    byte
 51         [40]    127    byte
 52         [41]    156    byte
 53         [42]    72    byte
 54         [43]    94    byte
 55         [44]    123    byte
 56         [45]    152    byte
 57         [46]    68    byte
 58         [47]    82    byte
 59         [48]    125    byte
 60         [49]    158    byte
 61         [50]    78    byte
 62         [51]    88    byte
 63         [52]    121    byte
 64         [53]    154    byte
 65         [54]    74    byte
 66         [55]    92    byte
 67         [56]    117    byte
 68         [57]    150    byte
 69         [58]    76    byte
 70         [59]    90    byte
 71         [60]    127    byte
 72         [61]    156    byte
 73         [62]    72    byte
 74         [63]    94    byte
 75         [64]    123    byte
 76         [65]    152    byte
 77         [66]    68    byte
 78         [67]    82    byte
 79         [68]    125    byte
 80         [69]    158    byte
 81         [70]    78    byte
 82         [71]    88    byte
 83         [72]    121    byte
 84         [73]    154    byte
 85         [74]    74    byte
 86         [75]    92    byte
 87         [76]    117    byte
 88         [77]    150    byte
 89         [78]    76    byte
 90         [79]    90    byte
 91         [80]    127    byte
 92         [81]    156    byte
 93         [82]    72    byte
 94         [83]    94    byte
 95         [84]    123    byte
 96         [85]    152    byte
 97         [86]    68    byte
 98         [87]    82    byte
 99         [88]    125    byte
100         [89]    158    byte
101         [90]    78    byte
102         [91]    88    byte
103         [92]    121    byte
104         [93]    154    byte
105         [94]    74    byte
106         [95]    92    byte
107         [96]    117    byte
108         [97]    150    byte
109         [98]    76    byte
110         [99]    90    byte
111         [100]    127    byte
112         [101]    156    byte
113         [102]    72    byte
114         [103]    94    byte
115         [104]    123    byte
116         [105]    152    byte
117         [106]    68    byte
118         [107]    82    byte
119         [108]    125    byte
120         [109]    158    byte
121         [110]    78    byte
122         [111]    88    byte
123         [112]    121    byte
124         [113]    154    byte
125         [114]    74    byte
126         [115]    92    byte
127         [116]    117    byte
128         [117]    150    byte
129         [118]    76    byte
130         [119]    90    byte
131         [120]    127    byte
132         [121]    156    byte
133         [122]    72    byte
134         [123]    94    byte
135         [124]    123    byte
136         [125]    152    byte
137         [126]    68    byte
138         [127]    82    byte
139         [128]    125    byte
140         [129]    158    byte
141         [130]    78    byte
142         [131]    88    byte
143         [132]    121    byte
144         [133]    154    byte
145         [134]    74    byte
146         [135]    92    byte
147         [136]    117    byte
148         [137]    150    byte
149         [138]    76    byte
150         [139]    90    byte
151         [140]    127    byte
152         [141]    156    byte
153         [142]    72    byte
154         [143]    94    byte
155         [144]    123    byte
156         [145]    152    byte
157         [146]    68    byte
158         [147]    82    byte
159         [148]    125    byte
160         [149]    158    byte
161         [150]    78    byte
162         [151]    88    byte
163         [152]    121    byte
164         [153]    154    byte
165         [154]    74    byte
166         [155]    92    byte
167         [156]    117    byte
168         [157]    150    byte
169         [158]    76    byte
170         [159]    90    byte
171         [160]    127    byte
172         [161]    156    byte
173         [162]    72    byte
174         [163]    94    byte
175         [164]    123    byte
176         [165]    152    byte
177         [166]    68    byte
178         [167]    82    byte
179         [168]    125    byte
180         [169]    158    byte
181         [170]    78    byte
182         [171]    88    byte
183         [172]    121    byte
184         [173]    154    byte
185         [174]    74    byte
186         [175]    92    byte
187         [176]    117    byte
188         [177]    150    byte
189         [178]    76    byte
190         [179]    90    byte
191         [180]    127    byte
192         [181]    156    byte
193         [182]    72    byte
194         [183]    94    byte
195         [184]    123    byte
196         [185]    152    byte
197         [186]    68    byte
198         [187]    82    byte
199         [188]    125    byte
200         [189]    158    byte
201         [190]    78    byte
202         [191]    88    byte
203         [192]    121    byte
204         [193]    154    byte
205         [194]    74    byte
206         [195]    92    byte
207         [196]    117    byte
208         [197]    150    byte
209         [198]    76    byte
210         [199]    90    byte
211         [200]    127    byte
212         [201]    156    byte
213         [202]    72    byte
214         [203]    94    byte
215         [204]    123    byte
216         [205]    152    byte
217         [206]    68    byte
218         [207]    82    byte
219         [208]    71    byte
複製代碼

 

 

代碼分析掩碼:

複製代碼
 1 /// <summary>
 2 ///判斷傳入數據是否存在掩碼
 3 /// 傳入數據:hi
 4 /// socket接收到的二進制數據:
 5 ///      1000000110000010 1101011011101001
 6 ///      111110 111000 10111110 10000000
 7 /// 掩碼異或的操作:
 8 ///             111110 111000 10111110 10000000
 9 ///   進行異或^ 111110 111001 11010110 11101001 
10 ///    結果:                   1101000  1101001
11 /// 數據樣例:
12 ///        [0]    129    byte
13 ///        [1]    130    byte
14 ///        [2]    214    byte
15 ///        [3]    233    byte
16 ///        [4]    62     byte
17 ///        [5]    56     byte
18 ///        [6]    190     byte
19 ///        [7]    128     byte
20 /// </summary>
21 /// <returns></returns>
22         private string UnWrap()
23         {
24             string result = string.Empty;
25 
26             // 計算非空位置
27             int lastStation = GetLastZero();
28 
29             // 利用掩碼對org-data進行異或
30             int frame_masking_key = 1;
31             for (int i = 6; i <= lastStation; i++)
32             {
33                 frame_masking_key = i % 4;
34                 frame_masking_key = frame_masking_key == 0 ? 4 : frame_masking_key;
35                 frame_masking_key = frame_masking_key == 1 ? 5 : frame_masking_key;
36                 receivedDataBuffer[i] = Convert.ToByte(receivedDataBuffer[i] ^ receivedDataBuffer[frame_masking_key]);
37             }
38 
39             System.Text.UTF8Encoding decoder = new System.Text.UTF8Encoding();
40             result = decoder.GetString(receivedDataBuffer, 6, lastStation - 6 + 1);
41 
42             return result;
43 
44         }
複製代碼

 

 

複製代碼
 1 /// <summary>
 2 /// 對傳入數據進行無掩碼轉換
 3 /// </summary>
 4 /// <returns></returns>
 5         public static byte[] Wrap(string msg, int maxBufferSize)
 6         {
 7             // 掩碼開始位置
 8             int masking_key_startIndex = 2;
 9 
10             byte[] msgByte = Encoding.UTF8.GetBytes(msg);
11 
12             // 計算掩碼開始位置
13             if (msgByte.Length <= 125)
14             {
15                 masking_key_startIndex = 2;
16             }
17             else if (msgByte.Length > 65536)
18             {
19                 masking_key_startIndex = 10;
20             }
21             else if (msgByte.Length > 125)
22             {
23                 masking_key_startIndex = 4;
24             }
25 
26             // 創建返回數據
27             byte[] result = new byte[msgByte.Length + masking_key_startIndex];
28 
29             // 開始計算ws-frame
30         // frame-fin + frame-rsv1 + frame-rsv2 + frame-rsv3 + frame-opcode
31             result[0] = 0x81;       // 129
32 
33             // frame-masked+frame-payload-length
34             // 從第9個字節開始是 1111101=125,掩碼是第3-第6個數據
35             // 從第9個字節開始是 1111110>=126,掩碼是第5-第8個數據
36             if (msgByte.Length <= 125)
37             {
38                 result[1] = Convert.ToByte(msgByte.Length);
39             }
40             else if (msgByte.Length > 65536)
41             {
42                 result[1] = 0x7F;   // 127
43             }
44             else if (msgByte.Length > 125)
45             {
46                 result[1] = 0x7E;   // 126
47                 result[2] = Convert.ToByte(msgByte.Length >> 8);
48                 result[3] = Convert.ToByte(msgByte.Length % 256);
49             }
50 
51             // 將數據編碼放到最後
52             Array.Copy(msgByte, 0, result, masking_key_startIndex, msgByte.Length);
53 
54             return result;
55         }
複製代碼



 

 WebSocket 協議:

 

複製代碼
public enum WebSocketProtocol
    {
        /*
         * 
         * Request
            GET /WebIM5?uaid=200513807p8912-8de8c7e2-c963-4f67-8aca-8028797efbc1&re=0 HTTP/1.1
            Upgrade: WebSocket
            Connection: Upgrade
            Host: 10.10.150.60:5002
            Origin: https://localhost:444
            Sec-WebSocket-Key1: 3+3 1  8kgV"m 0 8  64u43
            Sec-WebSocket-Key2: 3_7891 6 4 `50 `8
         * 
         * Response
            HTTP/1.1 101 WebSocket Protocol Handshake
            Upgrade: WebSocket
            Connection: Upgrade
            Sec-WebSocket-Origin: https://localhost:444
            Sec-WebSocket-Location: ws://192.168.110.....
            Sec-WebSocket-Protocol: WebIM5
         * 
         *  asdfalskdfa
         * */
        draft_00 = 0,

        /*
         * 
         * Request
            GET /WebIM5?uaid=200513807p8912-2e695e5b-9b46-4511-b59e-28981b4ab327&re=0 HTTP/1.1
            Upgrade: websocket
            Connection: Upgrade
            Host: 10.10.150.60:5002
            Origin: https://localhost:444
            Sec-WebSocket-Key: 1o4Jk9XPGvTX66OxmNMaww==
            Sec-WebSocket-Version: 13
         * 
         * Response
            HTTP/1.1 101 Switching Protocols
            Upgrade: websocket
            Connection: Upgrade
            Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
            Sec-WebSocket-Protocol: WebIM5
         * */
        draft_17 = 17
    }
複製代碼

 

 支持safari+chrome+firefox:

複製代碼
 1 // 開始連接到服務器
 2     var pollingInterval;
 3     _ws = new WebSocket("ws://192.168.0.103:5002/WebIM5?uaid=200513807p8912-5a78ae8a-cabb-46ee-8d8a-85874bbc942c&re=0");
 4     //_ws = new window.MozWebSocket("ws://192.168.0.103:5002/WebIM5?uaid=200513807p8912-5a78ae8a-cabb-46ee-8d8a-85874bbc942c&re=0");
 5     _ws.onopen = function () {
 6         alert("onopen");
 7 
 8         _socketCreated = true;
 9         var args
10         _ws.send("1234567890");
11         _ws.send("33322233");
12     };
13     _ws.onmessage = function (event) {
14         console.log("event.data=" + event.data);
15                     
16     };
17     _ws.onclose = function () {
18         alert("onclose");
19         console.log("onclose");
20     };
21     _ws.onerror = function () {
22         console.log("onerror");
23     };
24     function send() {
25         _ws.send(document.getElementById("msg").value);
26     }
複製代碼

 

其中,safari和chrome都是 :_ws = new WebSocket("ws://ip:port");  但是firefox是:_ws = new window.MozWebSocket("ws://ip:port");

發佈了24 篇原創文章 · 獲贊 4 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章