写在前面:
微软官方对websocket的直接支持很差,教程也写得不用心。还要用户自己去转字节数组和字符串,太过分了!
毕竟主推SignalR。
本文是在官方教程的基础上,对其进行了一些简单的讲解,和方法提取、封装,以期降低学习难度。
步骤描述:
1、随便建了个普通的mvc项目(任意带控制器的.net项目道理相同,都应该可以)。在Program.cs中,添加websocket支持。见以下代码第24行。
1 namespace WebApplication2 2 { 3 public class Program 4 { 5 public static void Main(string[] args) 6 { 7 var builder = WebApplication.CreateBuilder(args); 8 9 // Add services to the container. 10 builder.Services.AddControllersWithViews(); 11 12 var app = builder.Build(); 13 14 // Configure the HTTP request pipeline. 15 if (!app.Environment.IsDevelopment()) 16 { 17 app.UseExceptionHandler("/Home/Error"); 18 } 19 app.UseStaticFiles(); 20 21 app.UseRouting(); 22 23 //启用websocket 24 app.UseWebSockets(); 25 //app.UseAuthorization(); 26 27 app.MapControllerRoute( 28 name: "default", 29 pattern: "{controller=Home}/{action=Index}/{id?}"); 30 31 app.Run(); 32 } 33 } 34 }
只支持ws或wss请求。
2、控制器代码如下。14行注册路由(即要以类似 ws://xxxx/ws 的方式访问)
1 using Microsoft.AspNetCore.Http; 2 using Microsoft.AspNetCore.Mvc; 3 using System.Net.WebSockets; 4 using System.Text; 5 using WebApplication2.Function; 6 7 namespace WebApplication2.Controllers 8 { 9 //[Route("api/[controller]")] 10 //[ApiController] 11 public class WebSocketController : ControllerBase 12 { 13 //注册路由 14 [Route("/ws")] 15 public async Task Get() 16 { 17 //如果是websocket请求 18 if (HttpContext.WebSockets.IsWebSocketRequest) 19 { 20 //获得连接 21 using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); 22 //处理程序 23 await 处理程序(webSocket); 24 } 25 else 26 { 27 HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest; 28 } 29 } 30 31 async Task 处理程序(WebSocket w) 32 { 33 string s; 34 bool f; 35 //简单的处理,收消息,修改,发送。 36 (f,s)=await WebSocket操作.收(w); 37 while(f) 38 { 39 s = "server:" + s; 40 await WebSocket操作.发(w, s); 41 (f,s)= await WebSocket操作.收(w); 42 } 43 await WebSocket操作.关(w); 44 } 45 } 46 }
注释都比较清楚,不赘述。
31行开始的处理程序,从设计的角度,不应该出现在控制器里。介意的读者,请自行处理。
WebSocket操作类,见后面。
3、WebSocket操作类:
1 using System; 2 using System.Net.WebSockets; 3 using System.Text; 4 5 namespace WebApplication2.Function 6 { 7 //对微软官方示例的简单封装, 8 public class WebSocket操作 9 { 10 //接收消息,bool指示收到的是不是关闭消息,string是收到的内容。 11 public static async Task<(bool,string)> 收(WebSocket ws) 12 { 13 //接收大小最多4k。 14 var buffer = new byte[1024 * 4]; 15 string s; 16 //把消息收到字节数组中 17 var receiveResult = await ws.ReceiveAsync( 18 new ArraySegment<byte>(buffer), CancellationToken.None); 19 //如果不是关闭消息 20 if (!receiveResult.CloseStatus.HasValue) 21 { 22 //转换为字符串返回 23 s = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count); 24 return (true,s); 25 } 26 else 27 { 28 s = "无"; 29 return (false,s); 30 } 31 } 32 33 //发送消息 34 public static async Task 发(WebSocket ws, string s) 35 { 36 //消息转换成字节数组 37 var buffer = Encoding.UTF8.GetBytes(s); 38 //发送 39 await ws.SendAsync( 40 new ArraySegment<byte>(buffer, 0, buffer.Length), 41 WebSocketMessageType.Text, 42 true, 43 CancellationToken.None); 44 } 45 public static async Task 关(WebSocket ws) 46 { 47 //官方例子里,status是接收到的关闭类型。这里偷懒,应该也不影响用。 48 var status = ws.CloseStatus == null ? WebSocketCloseStatus.Empty :ws.CloseStatus.Value; 49 //关闭 50 await ws.CloseAsync( 51 status, 52 ws.CloseStatusDescription, 53 CancellationToken.None); 54 } 55 } 56 }
其中17-20,39-44,50-53行的代码,基本来自官方例程。我不求甚解,大家随意。
至此,服务端完成。
客户端,可以完全照搬 使用js和nodejs完成websocket双向通讯 里的web客户端。
运行结果:
成功,调试通过。
标签:websocket,C#,app,await,JS,ws,using,WebSocket,public From: https://www.cnblogs.com/wanjinliu/p/17909477.html