#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.