在学习使用websocket之前我们先了解一下websocket:
WebSocket是一种在单个TCP连接上进行全双工通信的通信协议。与HTTP协议不同,它允许服务器主动向客户端发送数据,而不需要客户端明确地请求。这使得WebSocket非常适合需要实时或持续通信的应用程序,例如在线聊天、实时游戏、股票市场更新等。
websocket介绍
以下是WebSocket的一些关键特点 :
全双工通信 :WebSocket允许客户端和服务器在同一时间内彼此发送数据,而不需要等待对方的响应。这种实时性使其成为许多实时应用程序的首选协议。
持久连接 :与HTTP请求-响应模型不同,WebSocket连接在客户端和服务器之间保持打开状态,直到一方选择关闭连接。这消除了频繁地建立和终止连接的开销。
较低的开销 :WebSocket在已建立连接的基础上传输数据,减少了与每个请求都要建立新连接的HTTP协议的开销。
轻量级标头 :WebSocket协议的标头数据相对较小,这有助于减少数据传输时的开销。
跨域支持 :WebSocket协议支持跨域通信,这意味着您可以在不同域之间建立WebSocket连接。
安全性 :与HTTP一样,WebSocket可以通过使用TLS/SSL来加密通信,确保数据的安全性。
要建立WebSocket连接,客户端和服务器之间的初始握手是通过HTTP完成的。一旦握手成功,连接升级为WebSocket连接,允许双方直接交换数据帧。数据帧可以是文本数据或二进制数据,具体取决于应用程序的需求。
下面是一个示意性的WebSocket握手过程 :
客户端发起WebSocket握手请求,包含特定的HTTP头信息。
服务器响应握手请求,同样包含特定的HTTP头信息。
握手成功后,连接从HTTP协议升级到WebSocket协议。
客户端和服务器可以通过发送数据帧进行实时通信,直到其中一方关闭连接。
Ajax长轮询介绍
在websocket不被广泛使用之前Ajax的长轮询比较流行,本质上两者都是用于实现实时通信的技术 ,但是它们之间有以下区别:
连接方式 :Ajax长轮询使用的是HTTP协议,而Websocket使用的是WebSocket协议。
性能 :Ajax长轮询中客户端需要不断向服务器发送HTTP请求,服务器在收到请求后才能返回数据给客户端。这种方式会导致不必要的网络延迟和服务器压力,性能相对较差。Websocket采用双向通信方式,只需要建立一次连接,即可实现实时通信,性能较好。
兼容性 :Ajax长轮询在大多数浏览器中都可以使用,但是在一些较老的浏览器中可能会有兼容性问题。Websocket需要浏览器支持HTML5才能使用。
实时性:Ajax长轮询的实时性较差,因为客户端需要不断向服务器发送请求,而服务器在收到请求后才能返回数据。Websocket的实时性较好,因为它采用双向通信方式。
完整代码 https://download.csdn.net/download/qq_39569480/88264479
websocket用例
后端代码
1.注册服务
首先要在Startup文件中的ConfigureServices方法中注册HttpContextAccessor
csharp
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication3", Version = "v1" });
});
services.AddHttpContextAccessor();//注册http
}
其次在Startup文件中的Configure方法中添加wesocket
csharp
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication2 v1"));
}
app.UseWebSockets();//添加websocket
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
2.创建服务
首先定义一个Controller或者Service
注入IHttpContextAccessor以便获取socket请求
声明全局变量用于存储socket链接,这里没有将socket存储到类似redis或数据库中,因为socket链接不能被反序列化,如果有更好方法的小伙版可以留言。这里的socket链接池只要服务不停 链接就会一直存在。
csharp
[ApiController]
public class WebSocketDemoController : ControllerBase
{
private readonly IHttpContextAccessor _httpContextAccessor;
private static Dictionary<string, WebSocket> _dic = new Dictionary<string, WebSocket>();
public WebSocketDemoController(IHttpContextAccessor httpContextAccessor)
{
this._httpContextAccessor = httpContextAccessor;
}
}
编写socket接口
HttpGet("/WsService")\]这里定义了socket的名字
http协议:访问时直接通过**ws://Ip:Port/WsService** 去访问
https协议:访问时直接通过**wss://Ip:Port/WsService**去访问
```csharp
[HttpGet("/WsService")]
public async Task Get()
{
//Logger.LogInformation(CurrentUser.Id + CurrentUser.Name);
if (_httpContextAccessor.HttpContext.WebSockets.IsWebSocketRequest)
{
//string token= _httpContextAccessor.HttpContext.Request.Headers["Sec-WebSocket-Protocol"];
Console.WriteLine("有链接进入");
//接受websocket客户端连接
var webSocket = await _httpContextAccessor.HttpContext.WebSockets.AcceptWebSocketAsync();
//await ReadWriteWebSocektAsync("Add",CurrentUser.Id.ToString(),webSocket); //如果用户的连接不存在加进缓存
await Echo(webSocket);
}
else
{
//不是websocket客户端请求 ]
_httpContextAccessor.HttpContext.Response.StatusCode = 400;
}
}
```
**消息处理方法**
```csharp
///