WebSocket客户端无法握手
我最近开始使用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
块永远不会被触发 - 尽管我看到客户端连接尝试已经通过。
基于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();
}
现在我得到一个有效的连接,但无法与服务器发送/接收数据 - 但这是另一个故事,我猜。
不错的工作,我实际上发现你不需要包含聊天和超级聊天协议,你只需要在响应结束时添加额外的1行。 – Jason 2013-06-02 08:58:00
@EnglishMaster你完全正确,包括协议是一个红鲱鱼,显然我错过了一个非常重要的'\ r \ n \ r \ n'来表示传输的结束。 – 2014-07-21 11:52:48
您是否尝试过不设置协议? (即离开聊天位) – djc 2013-03-19 16:10:41
@djc不幸的是,对我而言。在尝试使用相同的错误之前,我没有聊天。 – 2013-03-19 16:18:31
也许你应该填写响应键,所以我可以用我自己的代码来检查它。 (或另一对匹配的Sec-WebSocket-Key和Sec-WebSocket-Accept值。) – djc 2013-03-19 16:33:50