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

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

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


Ниже приведен код моего сервера: ПРИМЕЧАНИЕ. Я изменил комментарии с "V" в VB на C# "//", так как он отображался в виде строк в кодовых блоках переполнения стека.

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: " & 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. Однако веб-сокет по какой-то причине сразу закрывается, когда вторая строка попадает в 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, так как мы спешили, но эй, наконец-то добрался. Надеюсь, что если кто-то еще ударит по нему, он не застрянет на нем так долго, как я!

Другие вопросы по тегам