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