Websocket 服务器问题:onOpen 命中客户端,但服务器 websocket 处理程序 OnOpen 和其他事件从未命中
Websocket Server Issue: onOpen hit client side, but server websocket handler OnOpen and other events never hit
我对 websockets 和 WebAPI 非常陌生(我们的系统一直都是 .NET MVC,而不是 WebAPI),所以我很可能只是遗漏了一些明显的东西(我希望)。
我正在尝试实现一个简单的客户端来玩。我在 .NET 中工作(遗憾地)VB,我试图让 websocket 工作,并点击 OnOpen/Message/Close 事件服务器和客户端。
我的代码在下面,但简而言之,websocket 握手似乎没有任何问题,因为我在 javascript 中的 onOpen() 事件被命中,当我输出 readyState 它的 1 时。但是 OnOpen 没有被击中 server side
输出结果如下所示:
立即就绪:0
开启就绪状态:1
套接字已关闭
我的 WebSocketHandler 的构造函数被命中(例如,如果我在 MyBase.New() 行上抛出一个断点,它就会命中)。但是 OnOpen 永远不会被击中,并且套接字立即击中 js 中的 onclose 事件。我应该做些什么来保持套接字打开?为什么 OnOpen 不会被击中?
我的代码如下:
Javascript:
var wsUri = 'ws://' + window.location.hostname + '/api/Chat?username=hello';
var output;
$(document).ready(function () {
//setup and fire
output = document.getElementById("output");
testWebSocket();
})
function testWebSocket() {
//Instantiate the websocket, hopefully opening it
websocket = new WebSocket(wsUri);
writeToScreen("IMMEDIATE READYSTATE: " + websocket.readyState);
//bind event handlers
websocket.onopen = function (evt) { onOpen(evt) };
websocket.onclose = function (evt) { onClose(evt) };
websocket.onmessage = function (evt) { onMessage(evt) };
websocket.onerror = function (evt) { onError(evt) };
}
function onOpen(evt) {
writeToScreen("ONOPEN READYSTATE: " + websocket.readyState);
websocket.send("Websocket's open!")
}
function onClose(evt) {
writeToScreen("Socket closed");
}
function onMessage(evt) {
writeToScreen('RECEIVED: ' + evt.data);
}
function onError(evt) {
writeToScreen('ERROR:' + evt.data);
}
function writeToScreen(message) {
var messageToAppend = document.createElement("p");
messageToAppend.style.wordWrap = "break-word";
messageToAppend.innerHTML = '<span>' + message + '</span>';
output.appendChild(messageToAppend);
}
服务器:
Public Class ChatController
Inherits ApiController
Public Function [Get](username As String) As HttpResponseMessage
If HttpContext.Current.IsWebSocketRequest Then
HttpContext.Current.AcceptWebSocketRequest(Function() Tasks.Task.FromResult(New ChatWebSocketHandler(username)))
Return Request.CreateResponse(HttpStatusCode.SwitchingProtocols)
Else
Return Request.CreateResponse(HttpStatusCode.BadRequest)
End If
End Function
Private Class ChatWebSocketHandler
Inherits Microsoft.Web.WebSockets.WebSocketHandler
Public Sub New(username As String)
MyBase.New()
'Do stuff with username eventually.
End Sub
Public Overrides Sub OnOpen()
Debug.WriteLine("Websocket is open")
End Sub
Public Overrides Sub OnMessage(message As String)
Debug.WriteLine("Message Received: " & message)
End Sub
Public Overrides Sub OnClose()
Debug.WriteLine("Websocket Closed")
MyBase.OnClose()
End Sub
End Class
End Class
老实说,我不能 100% 肯定是什么解决了这个问题,但我非常怀疑。
我在我的代码中包含了太多的名称空间,我相信编译器等在实际 运行 中存在一些混乱。显然 Microsoft.Web.Websockets 和 SignalR 的命名空间都包含 WebSocketHandler。虽然我不知道 SignalR 的所有来龙去脉,但看起来 THAT 命名空间中的 WebSocketHandler 并不意味着要在 SignalR 之外使用。我相信 class 被引用而不是 Microsoft.Web.Websockets 中的那个,因为它现在可以工作,但我真的没有做太多改变。它还让我可以通过实例化处理程序的新实例来直接调用构造函数,而不必在 lambda 函数中调用它。
无论如何,如果其他人遇到类似问题,请确保您引用的是正确的!
我对 websockets 和 WebAPI 非常陌生(我们的系统一直都是 .NET MVC,而不是 WebAPI),所以我很可能只是遗漏了一些明显的东西(我希望)。
我正在尝试实现一个简单的客户端来玩。我在 .NET 中工作(遗憾地)VB,我试图让 websocket 工作,并点击 OnOpen/Message/Close 事件服务器和客户端。
我的代码在下面,但简而言之,websocket 握手似乎没有任何问题,因为我在 javascript 中的 onOpen() 事件被命中,当我输出 readyState 它的 1 时。但是 OnOpen 没有被击中 server side
输出结果如下所示:
立即就绪:0
开启就绪状态:1
套接字已关闭
我的 WebSocketHandler 的构造函数被命中(例如,如果我在 MyBase.New() 行上抛出一个断点,它就会命中)。但是 OnOpen 永远不会被击中,并且套接字立即击中 js 中的 onclose 事件。我应该做些什么来保持套接字打开?为什么 OnOpen 不会被击中?
我的代码如下:
Javascript:
var wsUri = 'ws://' + window.location.hostname + '/api/Chat?username=hello';
var output;
$(document).ready(function () {
//setup and fire
output = document.getElementById("output");
testWebSocket();
})
function testWebSocket() {
//Instantiate the websocket, hopefully opening it
websocket = new WebSocket(wsUri);
writeToScreen("IMMEDIATE READYSTATE: " + websocket.readyState);
//bind event handlers
websocket.onopen = function (evt) { onOpen(evt) };
websocket.onclose = function (evt) { onClose(evt) };
websocket.onmessage = function (evt) { onMessage(evt) };
websocket.onerror = function (evt) { onError(evt) };
}
function onOpen(evt) {
writeToScreen("ONOPEN READYSTATE: " + websocket.readyState);
websocket.send("Websocket's open!")
}
function onClose(evt) {
writeToScreen("Socket closed");
}
function onMessage(evt) {
writeToScreen('RECEIVED: ' + evt.data);
}
function onError(evt) {
writeToScreen('ERROR:' + evt.data);
}
function writeToScreen(message) {
var messageToAppend = document.createElement("p");
messageToAppend.style.wordWrap = "break-word";
messageToAppend.innerHTML = '<span>' + message + '</span>';
output.appendChild(messageToAppend);
}
服务器:
Public Class ChatController
Inherits ApiController
Public Function [Get](username As String) As HttpResponseMessage
If HttpContext.Current.IsWebSocketRequest Then
HttpContext.Current.AcceptWebSocketRequest(Function() Tasks.Task.FromResult(New ChatWebSocketHandler(username)))
Return Request.CreateResponse(HttpStatusCode.SwitchingProtocols)
Else
Return Request.CreateResponse(HttpStatusCode.BadRequest)
End If
End Function
Private Class ChatWebSocketHandler
Inherits Microsoft.Web.WebSockets.WebSocketHandler
Public Sub New(username As String)
MyBase.New()
'Do stuff with username eventually.
End Sub
Public Overrides Sub OnOpen()
Debug.WriteLine("Websocket is open")
End Sub
Public Overrides Sub OnMessage(message As String)
Debug.WriteLine("Message Received: " & message)
End Sub
Public Overrides Sub OnClose()
Debug.WriteLine("Websocket Closed")
MyBase.OnClose()
End Sub
End Class
End Class
老实说,我不能 100% 肯定是什么解决了这个问题,但我非常怀疑。
我在我的代码中包含了太多的名称空间,我相信编译器等在实际 运行 中存在一些混乱。显然 Microsoft.Web.Websockets 和 SignalR 的命名空间都包含 WebSocketHandler。虽然我不知道 SignalR 的所有来龙去脉,但看起来 THAT 命名空间中的 WebSocketHandler 并不意味着要在 SignalR 之外使用。我相信 class 被引用而不是 Microsoft.Web.Websockets 中的那个,因为它现在可以工作,但我真的没有做太多改变。它还让我可以通过实例化处理程序的新实例来直接调用构造函数,而不必在 lambda 函数中调用它。
无论如何,如果其他人遇到类似问题,请确保您引用的是正确的!