Websocket 服务器问题:onOpen 命中客户端,但服务器 websocket 处理程序 OnOpen 和其他事件从未命中

Posted

技术标签:

【中文标题】Websocket 服务器问题:onOpen 命中客户端,但服务器 websocket 处理程序 OnOpen 和其他事件从未命中【英文标题】:Websocket Server Issue: onOpen hit client side, but server websocket handler OnOpen and other events never hit 【发布时间】:2016-10-11 22:24:18 【问题描述】:

我对 websockets 和 WebAPI 非常陌生(我们的系统都是 .NET MVC,只是不是 WebAPI),所以我很可能只是遗漏了一些明显的东西(我希望如此)。

我正在尝试实现一个简单的客户端来玩。我在(可悲的)VB中使用.NET,我试图让websocket正常工作,并点击OnOpen/Message/Close事件服务器和客户端。

我的代码在下面,但简而言之,websocket 握手似乎没有任何问题,因为我在 javascript 中的 onOpen() 事件被命中,并且当我输出 readyState 时它的 1。但是 OnOpen 不会受到 服务器 方面的影响

输出最终看起来像这样:

立即就绪状态: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

【问题讨论】:

快速说明:发布此内容后,我在我的服务器代码中添加了对 OnError 的覆盖,以查看它是否碰巧遇到此问题,但无济于事 javascript 似乎工作得很好。应该是你的服务器代码的错(注意:我没有用jquery测试,我只是使用window.addEventListener("load", testWebSocket, false);并连接到ws://echo.websocket.org,这在此处作为测试服务器很有用) 知道我的服务器出了什么问题吗? HTTP 请求似乎正在实现,将其识别为 WebSocketRequest,然后毫无错误地接受它,此外,我的 WebSocketHandler 的构造函数也被命中,再次没有错误。但是它就像它立即死亡(或者可能永远不会完全实例化,因为 OnOpen() 永远不会到达服务器端?)。 我以前从未使用过VB,所以我无法对此发表有根据的评论。我总是使用开源 websocket 服务器库,例如一个 MIT 许可证,所以我也没有过多地研究 websocket 协议的细节。 【参考方案1】:

说实话,我不能 100% 肯定地说是什么解决了这个问题,但我非常怀疑。

我在我的代码中包含了太多的命名空间,我相信编译器等在实际运行时存在一些混乱。显然 Microsoft.Web.Websockets 和 SignalR 的命名空间都包含 WebSocketHandler。虽然我不知道 SignalR 的所有细节,但看起来那个命名空间中的 WebSocketHandler 并不打算在 SignalR 之外使用。我相信这个类被引用而不是 Microsoft.Web.Websockets 中的那个,因为它现在可以工作,但我真的没有改变太多。它还让我可以通过实例化处理程序的新实例来直接调用构造函数,而不必在 lambda 函数中调用它。

无论如何,如果其他人有类似的问题,请确保您引用的是正确的!

【讨论】:

以上是关于Websocket 服务器问题:onOpen 命中客户端,但服务器 websocket 处理程序 OnOpen 和其他事件从未命中的主要内容,如果未能解决你的问题,请参考以下文章

Rails WebSocket 客户端永远不会触发 OnOpen

HTML5 Websocket 连接到 Windows .NET 服务器,但没有收到 WebSocket.onopen 通知。

Javascript - WebSocket OnOpen 事件未触发

Java websocket在onOpen函数中获取自定义标头

Java EE7 websocket 初始化 - 在第一个 @OnOpen 之前实现逻辑

javascript 在 onopen 事件中获取 websocket 错误