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