gpt4 book ai didi

Asp.Net 作为客户端打开 websocket

转载 作者:行者123 更新时间:2023-12-04 21:05:37 30 4
gpt4 key购买 nike

在我的应用程序中,我使用 SignalR 通过我的客户端进行消息传递。然而,该应用程序有一个到另一台服务器的 websocket 连接,用于通知如下:

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);
}
}
}
}

在我的 javascript 文件中处理我插入的 signalR 方法
应该从 signalR 触发的 onMessage 方法。 (与我插入所有由 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 的最后处理 websocket 并释放我的监听器的方法。 (不再从 await webSocket.ReceiveAsync 捕获发送的任何消息)。在什么情况下会发生这种情况,我应该寻找什么?
  • 收到消息后,我将 json 结果正确反序列化为 WebSocketNotification,但我的 javascript 函数 onMessage 永远不会触发。我错过了什么?

  • 更新 2
    关于第二个问题,我通过更改使其工作
    repHub.client.onMessage => repHub.client.onmessage

    我觉得它很奇怪,因为我使用signalR的报告中心在服务器端的所有方法都是首字母大写的camelCase,而客户端的所有方法都是简单的camelCase。为什么这个案例不一样?我将不胜感激。

    更新 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://stackoverflow.com/questions/26744420/net-websocket-closeoutputasync-vs-closeasync
    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 进入最后并被处理之前得到的错误中,我得到以下错误和堆栈跟踪
    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

    我想我应该处理它并可能再次打开连接。
    现在几乎这是我唯一的问题(如果没有其他东西可寻找):

    这是最好的方式吗?我应该检查更多关于为什么我的连接关闭的信息吗?

    最佳答案

    关于你的最后一个问题,你可以从这个 post 中得到一些见解。 .

    似乎 WebSockets 可能因多种原因关闭,因此最好的方法是处理 WebSocket 关闭并可能重新打开它。

    但是,从答案看来,您还应该检查 IIS 服务器的 I/O 完成端口。

    处理由@user4624881 提供的案例的一种方法是使用 IAsyncResult.AsyncWaitHandle.WaitOne()用于 websocket 流产处理。

    像这样:

    Stream s = this.GetStream();
    IAsyncResult ar = s.BeginWrite(data, 0, data.Length, SendAsync, state);
    if (!ar.IsCompleted)
    ar.AsyncWaitHandle.WaitOne();

    关于Asp.Net 作为客户端打开 websocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46891990/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com