ASP.NET MVC Websocket server (WebAPI) завершение рукопожатия, но onOpen и другие функции событий не попадают на серверную сторону

#c# #vb.net #asp.net-web-api #websocket #system.net.websockets

#c# #vb.net #asp.net-web-api #websocket #system.net.websockets

Вопрос:

ПРИМЕЧАНИЕ: я помечаю это с помощью C #, поскольку считаю, что это привлечет более широкую аудиторию в ASP.NET сообщество.. Если это проблема, дайте мне знать, и я смогу ее устранить (C # — мой предпочтительный язык, но для этого проекта я вынужден писать на VB). Сервер websocket записывается с VB.NET ASP.NET WebAPI. Любая помощь была бы признательна.

Я просто хочу, чтобы соединение было открыто, оставалось открытым и отправляло быстрое строковое сообщение на сервер от клиента. Я сократил свой серверный код, чтобы он был как можно более простым, и опубликовал его полностью ниже.


Ниже приведен код моего сервера: ПРИМЕЧАНИЕ: я изменил комментарии с VB «‘» на C # «//», поскольку они отображались в виде строк в блоках кода stack overflow.

 Public Class ChatController
  Inherits ApiController

  //This is getting hit no problem
  Public Function [Get](username As String) As HttpResponseMessage

    If HttpContext.Current.IsWebSocketRequest Then
      Debug.WriteLine("Starting...") //This is successfully written out

      //Websocket request is accepted and no exceptions are raised..
      HttpContext.Current.AcceptWebSocketRequest(Function() Tasks.Task.FromResult(New ChatWebSocketHandler()))

      //Let the client know we're upgrading...
      Return Request.CreateResponse(HttpStatusCode.SwitchingProtocols)

    Else
      //Handle any bad requests
      Return Request.CreateResponse(HttpStatusCode.BadRequest)

    End If    
  End Function

  //This is my websocket handler - using the Microsoft Websockets class.
  Public Class ChatWebSocketHandler
    Inherits Microsoft.AspNet.SignalR.WebSockets.WebSocketHandler

    //This constructor is hit when the handshake happens, as expected.
    Public Sub New()
      MyBase.New(20000)
    End Sub

    //Everything from here down never gets hit, despite the client 
    //side onOpen/onClose event handlers being raised and readyState being 1.
    Public Overrides Sub OnOpen()
      //Breakpoints on either line below are not hit
      MyBase.OnOpen()

      Debug.WriteLine("Websocket is open")
    End Sub

    //I would expect this to get hit when websocket.send is called, 
    //no such luck.
    Public Overrides Sub OnMessage(message As String)
      Debug.WriteLine("Message Received: " amp; message)
    End Sub

    //never hit
    Public Overrides Sub OnError()
      MyBase.OnError()
      Debug.WriteLine("Websocket is open")
    End Sub

    //never hit
    Public Overrides Sub OnClose()
      Debug.WriteLine("Websocket Closed")

      MyBase.OnClose()

    End Sub
  End Class
End Class
  

Успешное рукопожатие:

При запуске рукопожатие кажется успешным, поскольку эта строка нажата (как и конструктор) и не выдает ошибку:

 //Server Side portion of handshake:
HttpContext.Current.AcceptWebSocketRequest(Function() 
               Tasks.Task.FromResult(New ChatWebSocketHandler()))

//Finish the handshake, let the browser know we're upgrading
Return Request.CreateResponse(HttpStatusCode.SwitchingProtocols)
  

Выполняется нажатие на функцию onOpen() на стороне клиента, которая записывает состояние готовности, равное 1. Однако по какой-то причине websocket немедленно закрывается при попадании второй строки в onOpen() (он переходит к обработчику OnClose())

 //Client side handlers:
function onOpen(evt) {
   writeToScreen("ONOPEN READYSTATE: "   websocket.readyState);
   websocket.send("Websocket's open!")
}

function onClose(evt) {
  writeToScreen("Socket closed");
}
  

Вопрос:

ChatWebSocketHandler.onOpen() (см. Код сервера внизу) никогда не отображается.Фактически, ни один из методов в этом классе (OnClose () , onError() и т. Д.) Никогда не Попадает, Кроме конструктора во время рукопожатия. Почему они не попали?

Обратите внимание, что, если я поставлю точку останова в строке websocket.send(), состояние готовности по-прежнему равно 1 перед выполнением строки, и в этой строке НЕ возникает ошибка, она просто переходит к websocket.Событие OnClose()

Заранее благодарю вас за помощь! При необходимости я могу опубликовать больше информации на стороне клиента.

Ответ №1:

Ну, я, наконец, понял это, и, конечно, это было что-то глупое 🙂

По-видимому, я допустил ошибку, сославшись на класс WebSocketHandler в SignalR — не похоже, что он предназначался для использования вне внутренних операций SignalR.

Мой новый код очень похож, единственное отличие заключается в том, что унаследованный класс websockethandler находится в пространстве имен Microsoft.Web.Websockets.

Еще одно отличие — эта строка:

 HttpContext.Current.AcceptWebSocketRequest(Function() Tasks.Task.FromResult(New ChatWebSocketHandler()))
  

Теперь просто:

 HttpContext.Current.AcceptWebSocketRequest(New ChatWebSocketHandler)
  

Потребовалось 2 дня, чтобы добраться туда, и теперь я в собачьей будке с командой PM, так как мы спешили, но, эй, наконец-то добрались. Надеюсь, если кто-то еще нажмет на это, он не застрянет на нем так долго, как я!

Комментарии:

1. то есть вы хотите сказать, что класс signalr WebSocketHandler не может использоваться как Microsoft.Web.Websockets для обработки запросов веб-сокетов?

2. По крайней мере, так кажется. Полагаю, это имеет смысл, если вы собираетесь использовать библиотеки SignalR, они, вероятно, ожидают, что вы будете использовать SignalR.