Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在asp.net core中使用WebSocket_C#_Asp.net Core_Websocket_Server_Client - Fatal编程技术网

C# 如何在asp.net core中使用WebSocket

C# 如何在asp.net core中使用WebSocket,c#,asp.net-core,websocket,server,client,C#,Asp.net Core,Websocket,Server,Client,我正在尝试开发一个游戏,其中我将记分板存储在一个文本文件中,该文件存储在服务器上(当前位于localhost上)。我使用HTTPGET和post调用与服务器通信,获取并发送所需的数据。现在我想实现WebSocket,以便从服务器向c#client发送通知。通知只会在控制台上为用户显示一条消息,例如,在mu情况下,我希望在每次将用户添加到记分板时,以及每次调用updateCoreboard方法时,都向用户显示一条消息。根据我在网上找到的教程,我已经成功地构建了以下代码,有谁能让我更清楚地了解如何为

我正在尝试开发一个游戏,其中我将记分板存储在一个文本文件中,该文件存储在服务器上(当前位于localhost上)。我使用HTTPGET和post调用与服务器通信,获取并发送所需的数据。现在我想实现WebSocket,以便从服务器向c#client发送通知。通知只会在控制台上为用户显示一条消息,例如,在mu情况下,我希望在每次将用户添加到记分板时,以及每次调用updateCoreboard方法时,都向用户显示一条消息。根据我在网上找到的教程,我已经成功地构建了以下代码,有谁能让我更清楚地了解如何为服务器构建websocket以及如何在客户端初始化websocket?多谢各位

Startup.cs(服务器)

public void配置(IApplicationBuilder应用程序,IHostEnvironment环境)
{
//删除的代码
var webSocketOptions=新的webSocketOptions()
{
KeepAliveInterval=从秒开始的时间跨度(120),
ReceiveBufferSize=4*1024
};
app.UseWebSockets(webSocketOptions);
应用程序使用(异步(上下文,下一步)=>
{
if(context.Request.Path==“/ws”)
{
if(context.WebSockets.IsWebSocketRequest)
{
WebSocket WebSocket=等待上下文.WebSocket.AcceptWebSocketAsync();
等待回声(上下文、webSocket);
}
其他的
{
context.Response.StatusCode=400;
}
}
其他的
{
等待下一个();
}
});
}
专用异步任务回显(HttpContext上下文,WebSocket WebSocket)
{
var buffer=新字节[1024*4];
WebSocketReceiveResult结果=等待webSocket.ReceiveAsync(新的ArraySegment(缓冲区),CancellationToken.None);
而(!result.CloseStatus.HasValue)
{
等待webSocket.SendAsync(新的ArraySegment(缓冲区,0,result.Count),result.MessageType,result.EndOfMessage,CancellationToken.None);
结果=等待webSocket.ReceiveAsync(新的ArraySegment(缓冲区),CancellationToken.None);
}
等待webSocket.CloseAsync(result.CloseStatus.Value、result.CloseStatusDescription、CancellationToken.None);
}
HttpClass.cs(客户机)-在这里我调用http post请求

public async override Task<List<Scoreboard>> UpdateScoreBoards(string username, int attempts, int seconds, DateTime date)
            {
                HttpResponseMessage response = null;
                //Creating a new instance of object Scoreboard
                //deleted code

                var url = "http://localhost:5000/api/Scoreboard";

                var socket_url = new Uri("ws://localhost:5000"); 
                var exitEvent = new ManualResetEvent(false);
                using (var client = new WebsocketClient(socket_url))
                {
                    client.ReconnectTimeout = TimeSpan.FromSeconds(30);
                    client.ReconnectionHappened.Subscribe(info =>
                        Log.Information($"Reconnection happened, type: {info.Type}"));

                    client.MessageReceived.Subscribe(msg => Log.Information($"Message received: {msg}"));
                    await client.Start();

                    await Task.Run(() => client.Send("test"));

                    exitEvent.WaitOne();
                }

// deleted code
            }
public async override Task UpdateScoreBoards(字符串用户名、int次尝试、int秒、DateTime日期)
{
HttpResponseMessage响应=null;
//创建对象记分板的新实例
//删除的代码
变量url=”http://localhost:5000/api/Scoreboard";
var socket_url=newuri(“ws://localhost:5000”);
var exitEvent=新手动重置事件(false);
使用(var client=newwebsocketclient(socket\u url))
{
client.ReconnectTimeout=TimeSpan.FromSeconds(30);
客户端。发生了重新连接。订阅(信息=>
Log.Information($“发生了重新连接,类型:{info.type}”);
client.MessageReceived.Subscribe(msg=>Log.Information($“MessageReceived:{msg}”);
等待client.Start();
等待任务。运行(()=>client.Send(“test”);
exitEvent.WaitOne();
}
//删除的代码
}
有人能更清楚地告诉我如何为服务器构建websocket,以及如何在客户端初始化websocket吗

正如您引用的示例所示,利用ASP.NET Core中的WebSocket,我们可以在
Configure
方法中添加,然后添加/配置请求委托以检查和处理传入的WebSocket请求

在使用
AcceptWebSocketAsync()
方法将请求转换为WebSocket连接后,我们可以使用返回的WebSocket对象发送和接收消息

//received message
var mes = Encoding.UTF8.GetString(buffer, 0, result.Count);

//code logic here
//...

//create reply message
var reply_mes = $"You sent {mes}.";

byte[] reply_mes_buffer = Encoding.UTF8.GetBytes(reply_mes);

await webSocket.SendAsync(new ArraySegment<byte>(reply_mes_buffer, 0, reply_mes.Length), result.MessageType, result.EndOfMessage, CancellationToken.None);
Echo
方法中,我们还可以执行自定义代码逻辑,根据收到的消息生成和发送回复消息/通知

//收到的消息
var mes=Encoding.UTF8.GetString(缓冲区,0,结果.计数);
//这里的代码逻辑
//...
//创建回复消息
var reply_mes=$“您发送了{mes}。”;
byte[]reply_mes_buffer=Encoding.UTF8.GetBytes(reply_mes);
等待webSocket.SendAsync(新的数组分段(reply\u mes\u buffer,0,reply\u mes.Length),result.MessageType,result.EndOfMessage,CancellationToken.None);
此外,ASP.NET Core Signal是一个开源库,它简化了实时通信功能的实现。它确实支持WebSocket传输,我们可以轻松地将消息/通知推送到所有连接的客户端或指定的连接客户端子集


有关ASP.NET Core Signaler的更多信息,您可以查看此文档:

启动过程中,您只需要添加
UseWebsockets
中间件。 然后,您可以定义自己的中间件和过滤器连接,如果它们是
websocket
类型,如下所示:

启动

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            app.UseWebSockets();
            app.UseMiddleware<SocketWare>();
        }
在我的中间件中,我更喜欢将业务逻辑保存在一个单独的类中,该类将
Websocket
注入其中,如下所示:

客户端

public class ChatClient
{
   private Task writeTask;
   private Task readTask;
   private WebSocket socket;
   private CancellationTokenSource cts=new CancellationTokenSource();
   ChatClient(WebSocket socket)
   {
       this.socket=socket;
   }
   public async Task RunAsync()
   {
      this.readTask=Task.Run(async ()=>await ReadLoopAsync(cts.Token),cts.Token);
      this.writeTask=Task.Run(async()=>await WriteLoopAsync(cts.Token),cts.Token);
      await Task.WhenAny(this.readTask,this.writeTask);
   }
   public async Task WriteLoopAsync()
   {
       Memory<byte> buffer=ArrayPool<byte>.Shared.Rent(1024);
       try {
           while (true) {
              var result= await this.socket.ReceiveAsync(buffer,....);
              var usefulBuffer=buffer.Slice(0,result.Count).ToArray();
              var raw=Encoding.Utf8.GetString(usefulBuffer);
              //deserialize it to whatever you need
              //handle message as you please (store it somwhere whatever)
            }
        } catch (Exception ex) {

               //socket error handling
               //break loop or continue with go to
        }
   }
   public async Task ReadLoopAsync()
   {
          try {
            while (true) {
              
                var data = await this.[someMessageProvider].GetMessageAsync() //read below !!!
                var bytes = Encoding.UTF8.GetBytes(data);
                //send the message on the websocket
                await this.socket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
            }
        } catch (Exception ex) {

            //do incorrect message/socket disconnect logic
        }
   }
}
  • Redis发布/订阅
    检查Redis发布/订阅
    同时检查我的存储库 在我所在的github上 使用您需要的内容(websockets、redis、pub-sub)

  • RabbitMq
    作为消息总线的另一个选项是使用
    RabbitMq
    ,以获取有关C的更多信息
    public class SocketWare {
            private RequestDelegate next;
            public SocketWare(RequestDelegate _next) {
                this.next = _next;
            }
            public async Task Invoke(HttpContext context) {
                if (!context.WebSockets.IsWebSocketRequest) {
                    return;
                }
                var socket=await context.WebSockets.AcceptWebSocketAsync();
                await RunAsync(socket);
            }
            private async Task RunAsync(WebSocket socket) {
                try {
                    var client = new ChatClient(socket, this.store,this.channelRegistry);
                    await client.RunAsync();
                } catch (Exception ex) {
    
                    throw;
                }
                
            }
            
    
        }
    
    public class ChatClient
    {
       private Task writeTask;
       private Task readTask;
       private WebSocket socket;
       private CancellationTokenSource cts=new CancellationTokenSource();
       ChatClient(WebSocket socket)
       {
           this.socket=socket;
       }
       public async Task RunAsync()
       {
          this.readTask=Task.Run(async ()=>await ReadLoopAsync(cts.Token),cts.Token);
          this.writeTask=Task.Run(async()=>await WriteLoopAsync(cts.Token),cts.Token);
          await Task.WhenAny(this.readTask,this.writeTask);
       }
       public async Task WriteLoopAsync()
       {
           Memory<byte> buffer=ArrayPool<byte>.Shared.Rent(1024);
           try {
               while (true) {
                  var result= await this.socket.ReceiveAsync(buffer,....);
                  var usefulBuffer=buffer.Slice(0,result.Count).ToArray();
                  var raw=Encoding.Utf8.GetString(usefulBuffer);
                  //deserialize it to whatever you need
                  //handle message as you please (store it somwhere whatever)
                }
            } catch (Exception ex) {
    
                   //socket error handling
                   //break loop or continue with go to
            }
       }
       public async Task ReadLoopAsync()
       {
              try {
                while (true) {
                  
                    var data = await this.[someMessageProvider].GetMessageAsync() //read below !!!
                    var bytes = Encoding.UTF8.GetBytes(data);
                    //send the message on the websocket
                    await this.socket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
                }
            } catch (Exception ex) {
    
                //do incorrect message/socket disconnect logic
            }
       }
    }
    
    public UpdateController:Controller
    {
       private IConnection
       [HttpPost]
       [someroute]
       public void UpdateScoreboard(string someMessage)
       {
           this.connection.Publish("someChannel",someMessage);
       }
       [HttpPost]
       [someotherroute]
       public void DeletePlayer(string someOtherMessage)
       {
           this.connection.Publish("someChannel",someMessage);
       }
    }