2013-03-19 151 views
2

我最近開始使用HTML5 WebSockets,並且我有一個簡單的jQuery Web客戶端和一個控制檯應用程序服務器。在這裏手顫抖讀了之後就是我現在有客戶端:WebSocket客戶端無法握手

var socket = new WebSocket("ws://127.0.0.1:100", ["chat"]); 
socket.onopen = function() { 
    console.log(socket.readyState); 
} 

這發出以下到我的服務器:

GET/HTTP/1.1 
Upgrade: websocket 
Connection: Upgrade 
Host: 127.0.0.1:100 
Origin: http://localhost:57944 
Sec-WebSocket-Protocol: chat 
Pragma: no-cache 
Cache-Control: no-cache 
Sec-WebSocket-Key: dBQ0epP7wmgHDEJc6Me95Q== 
Sec-WebSocket-Version: 13 
Sec-WebSocket-Extensions: x-webkit-deflate-frame 

現在,我的服務器代碼。

首先,我通過客戶端上面發送的行讀取並找到Sec-WebSocket-Key值,並將其保存到我的變量key

然後我追加幻數Wikipedia article here這是258EAFA5-E914-47DA-95CA-C5AB0DC85B11。這導致了下面的代碼:

key = string.Concat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); 
using (SHA1 sha1 = SHA1.Create()) 
{ 
    byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key)); 
    responseKey = Convert.ToBase64String(hash); 
} 

最後,我的迴應的關鍵在我發送回客戶端的消息,這是施工時:

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Accept: u9guLPph1FeCPuOpFNs4F1b+UqY= 
Sec-WebSocket-Protocol: chat 
[blank line, as requested in spec] 

但是,我socket.readyState去從0到3,然後失敗並出現以下錯誤WebSocket connection to 'ws://127.0.0.1:100/' failed:

我讀過,這可能是我的服務器使用不兼容的協議到客戶端,但我不完全確定從哪裏開始尋找如果是這種情況。如果沒有,有沒有人有任何想法如何解決這個問題或我可以去更多的信息,因爲我有點難倒。

2013年3月21日

閱讀下面的內容@ DJC的評論後,我修改服務器代碼發回具有以下確認:

using (StreamWriter sw = new StreamWriter(ns, Encoding.UTF8)) 
{ 
    sw.NewLine = "\r\n\r\n"; 

    // get response and calculate responseKey here (getting bytes as UTF-8 from client) 

    sw.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake"); 
    sw.WriteLine("Upgrade: websocket"); 
    sw.WriteLine("Connection: Upgrade"); 
    sw.WriteLine("WebSocket-Origin: http://localhost:57944"); 
    sw.WriteLine("WebSocket-Location: 127.0.0.1:100"); 
    sw.WriteLine("Sec-WebSocket-Accept: " + responseKey); 
    sw.WriteLine(""); 
    sw.Flush(); 
} 

好了,我不再得到一個錯誤客戶端 - 但'socket.readyState'保持爲0,並且我的socket.onopen塊永遠不會被觸發 - 儘管我看到客戶端連接嘗試已經通過。

+0

您是否嘗試過不設置協議? (即離開聊天位) – djc 2013-03-19 16:10:41

+0

@djc不幸的是,對我而言。在嘗試使用相同的錯誤之前,我沒有聊天。 – 2013-03-19 16:18:31

+0

也許你應該填寫響應鍵,所以我可以用我自己的代碼來檢查它。 (或另一對匹配的Sec-WebSocket-Key和Sec-WebSocket-Accept值。) – djc 2013-03-19 16:33:50

回答

3

基於this specification我終於設法讓它工作。這裏是我的客戶端代碼:

var socket = new WebSocket("ws://localhost:8181/websession", ['chat','superchat']); 

socket.onopen = function() 
{ 
    $("div#messages").append("<p class=\"event\">Socket is connected.</p>"); 
    socket.send("Thanks!"); 
}; 

似乎對cookie管理納入websession並要求['chat','superchat']協議。

服務器:

using (TcpClient client = listener.AcceptTcpClient()) 
using (NetworkStream stream = client.GetStream()) 
using (StreamReader sr = new StreamReader(stream, Encoding.UTF8)) 
using (StreamWriter sw = new StreamWriter(stream, Encoding.UTF8)) 
{ 
    Dictionary<string, string> headers = new Dictionary<string, string>(); 
    string line = string.Empty; 
    while ((line = sr.ReadLine()) != string.Empty) 
    { 
     string[] tokens = line.Split(new char[] { ':' }, 2); 
     if (!string.IsNullOrWhiteSpace(line) && tokens.Length > 1) 
     { 
      headers[tokens[0]] = tokens[1].Trim(); 
     } 
    } 

    string responseKey = ""; 
    string key = string.Concat(headers["Sec-WebSocket-Key"], "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); 
    using (SHA1 sha1 = SHA1.Create()) 
    { 
     byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(key)); 
     responseKey = Convert.ToBase64String(hash); 
    } 

    sw.WriteLine("HTTP/1.1 101 Switching Protocols"); 
    sw.WriteLine("Upgrade: websocket"); 
    sw.WriteLine("Connection: Upgrade"); 
    sw.WriteLine("Sec-WebSocket-Accept: " + responseKey); 
    sw.WriteLine("Sec-WebSocket-Protocol: chat"); 
    sw.WriteLine(""); 
    sw.Flush(); 
} 

現在我得到一個有效的連接,但無法與服務器發送/接收數據 - 但這是另一個故事,我猜。

+2

不錯的工作,我實際上發現你不需要包含聊天和超級聊天協議,你只需要在響應結束時添加額外的1行。 – Jason 2013-06-02 08:58:00

+0

@EnglishMaster你完全正確,包括協議是一個紅鯡魚,顯然我錯過了一個非常重要的'\ r \ n \ r \ n'來表示傳輸的結束。 – 2014-07-21 11:52:48