在我的应用程序中,我使用SignalR通过客户端进行消息传递。然而,该应用程序与另一个服务器建立了websocket连接,以便接收类似以下内容的通知:
我想做的是从我的Asp.Net应用程序建立连接,并通过将消息推送到正确的客户端来自己处理所有传入的消息。 然而,我没有找到这种实现的示例。我找到的所有示例都是关于从我的服务器到客户端设置websocket连接。 (我必须提到我对异步函数不太熟悉,所以可能有一些与此相关的错误)
更新
从我找到的内容来看,最好且(可能)最简单的方法是使用ClientWebSocket。 尝试寻找一些示例,我找到了这个:Websocket - Server Using HttpListener and Client With ClientWebSocket 从这个示例中,似乎我可以创建一个websocket连接到我想要的终点。所以我就这样做了。
在处理SignalR方法的JavaScript文件中,我插入了onMessage方法,应该从SignalR触发。(与我插入的所有由SignalR处理的方法相同,并且它们都可以正常工作。)
我的问题和疑问如下:
我觉得有点奇怪,因为我的报告中心使用了signalR,服务器端的所有方法都是以大写字母开头的驼峰式命名法,而客户端的所有方法都是简单的驼峰式命名法。为什么这种情况不同呢?我会感激你的回答。
更新3
我在我的OnMessage方法中插入了一个try catch,像这样:
我想我应该处理它,然后可能再次打开连接。 现在基本上这是我的唯一问题(如果没有其他要查找的内容): 那是最好的方法吗?我应该检查一些其他原因导致连接关闭吗?
var wsURL = (isSecure() ? "wss://" : "ws://") + wsEndpointURI + "?token=" + token + "&lang=" + language
+ "&uid=" + wsUid,
notifierWs = new WebSocket(wsURL);
middlewareNotifierWs.onmessage = function (event) {
var notification = JSON.parse(event.data),
msg = notification.message;
// Show the notification
};
我想做的是从我的Asp.Net应用程序建立连接,并通过将消息推送到正确的客户端来自己处理所有传入的消息。 然而,我没有找到这种实现的示例。我找到的所有示例都是关于从我的服务器到客户端设置websocket连接。 (我必须提到我对异步函数不太熟悉,所以可能有一些与此相关的错误)
更新
从我找到的内容来看,最好且(可能)最简单的方法是使用ClientWebSocket。 尝试寻找一些示例,我找到了这个:Websocket - Server Using HttpListener and Client With ClientWebSocket 从这个示例中,似乎我可以创建一个websocket连接到我想要的终点。所以我就这样做了。
public static class Program
{
private static UTF8Encoding encoding = new UTF8Encoding();
public static async Task Connect()
{
ClientWebSocket webSocket = null;
try
{
var url = serverWebSocketConnectionUrl;
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
await Task.WhenAll(OnMessage(webSocket));
}
catch (Exception ex)
{
// Log it
}
finally
{
if (webSocket != null)
{
webSocket.Dispose();
}
}
}
public static async Task OnMessage(ClientWebSocket webSocket)
{
byte[] buffer = new byte[1024];
while (webSocket.State == WebSocketState.Open)
{
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
CancellationToken.None);
}
else
{
WebSocketNotification notification = Newtonsoft.Json.JsonConvert.DeserializeObject<WebSocketNotification>(Encoding.UTF8.GetString(buffer));
// Here I want to get to the signalR context and send my message to the correct user.
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ReportingHub>();
List<string> userIds = new List<string>();
userIds.Add(notification.Id);
hubContext.Clients.Users(userIds).OnMessage(notification);
}
}
}
}
在处理SignalR方法的JavaScript文件中,我插入了onMessage方法,应该从SignalR触发。(与我插入的所有由SignalR处理的方法相同,并且它们都可以正常工作。)
repHub.client.onMessage = function (notification) {
// Show the message
}
根据我所做的,目前的结果是:
- 我的 WebSocket 连接成功打开
- 然后我的调试器进入
await Task.WhenAll(OnMessage(webSocket));
的 onMessage 方法 - 之后,我的调试器在这一行等待:
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
- 当服务器发送消息时,我的调试继续并正确返回结果。
我的问题和疑问如下:
在我的
Connect
方法中的某些点会触发finally语句,导致websocket被释放并且监听器被解除。此时发送的任何消息都不会被await webSocket.ReceiveAsync
捕获。在什么情况下会发生这种情况,我应该注意什么?当收到消息时,我正确地将json结果反序列化为WebSocketNotification,但我的javascript函数onMessage从未触发。我漏掉了什么?
更新2 关于第二个问题,我通过更改
repHub.client.onMessage => repHub.client.onmessage
我觉得有点奇怪,因为我的报告中心使用了signalR,服务器端的所有方法都是以大写字母开头的驼峰式命名法,而客户端的所有方法都是简单的驼峰式命名法。为什么这种情况不同呢?我会感激你的回答。
更新3
我在我的OnMessage方法中插入了一个try catch,像这样:
public static async Task OnMessage(ClientWebSocket webSocket)
{
byte[] buffer = new byte[1024];
while (webSocket.State == WebSocketState.Open)
{
try
{
// Receive data on ClientWebSocket as an asynchronous operation
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
// If the server sends a message with message type for closure close the websocket connection
// Could use the CloseOutputAsync : https://dev59.com/Kl8d5IYBdhLWcg3wgya4
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
CancellationToken.None);
}
else
{
WebSocketNotification notification =
Newtonsoft.Json.JsonConvert.DeserializeObject<WebSocketNotification>(
Encoding.UTF8.GetString(buffer));
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ReportingHub>();
List<string> userIds = new List<string>();
userIds.Add(notification.Id);
hubContext.Clients.Users(userIds).OnMessage(notification);
}
}
catch (Exception ex)
{
var a = ex;
}
}
}
在我的 Connect 进入 finally 并被处理之前,我遇到了以下错误和堆栈跟踪
An internal WebSocket error occurred. Please see the innerException, if present, for more details.
at System.Net.WebSockets.WebSocketBase.ThrowIfConvertibleException(String methodName, Exception exception, CancellationToken cancellationToken, Boolean aborted)
at System.Net.WebSockets.WebSocketBase.<ReceiveAsyncCore>d__45.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at AthenaWeb.Infrastructure.NotificationWebSocket.<OnMessage>d__3.MoveNext() in C:\Branches\Notifications\trunk\AthenaWeb\Infrastructure\NotificationWebSocket.cs:line 69
我想我应该处理它,然后可能再次打开连接。 现在基本上这是我的唯一问题(如果没有其他要查找的内容): 那是最好的方法吗?我应该检查一些其他原因导致连接关闭吗?