ASP.NET Core WebSocket SuperSocket WS WSS

 ASP.NET Core 中的 WebSocket 支持

WebSocket 
HTML5 开始提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议,基于 TCP 传输协议,并复用 HTTP 的握手通道。
特点:全双工通讯,服务器可以主动向客户推送消息,客户也可以主动向服务器发送消息,支持二进制通信。

WebSocket 属性 
Socket.readyState
0 - 表示连接尚未建立。
1 - 表示连接已建立,可以进行通信。
2 - 表示连接正在进行关闭。
3 - 表示连接已经关闭或者连接不能打开

WebSocket 事件 
open    Socket.onopen    连接建立时触发
message    Socket.onmessage    客户端接收服务端数据时触发
error    Socket.onerror    通信发生错误时触发
close    Socket.onclose    连接关闭时触发

WebSocket 方法 
Socket.send():使用连接发送数据
Socket.close():关闭连接

WS: WebSocket
WSS: WebSocket Secure
WS是非安全的,WSS是安全的。非安全的没有证书,安全的需要SSL证书。
WS的体现形式是TCP + WS AS WS ,WSS的体现形式是TCP + TLS + WS AS WSS。
WS一般默认是80端口,而WSS默认是443端口,大多数网站用的就是80和433端口。
http协议下使用ws,https协议下使用wss。
webSocket = new WebSocket("ws://localhost:port/hub");
webSocket = new WebSocket("wss://localhost:port/hub");

1、配置中间件

app.UseWebSockets();

KeepAliveInterval - 向客户端发送“ping”帧的频率,以确保代理保持连接处于打开状态。 默认值为 2 分钟。
AllowedOrigins - 用于 WebSocket 请求的允许的 Origin 标头值列表。 默认情况下,允许使用所有源。 有关详细信息,请参阅以下“WebSocket 源限制”。

2、Startup.cs

namespace WebAPI
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseStaticFiles();
            app.UseRouting();

            var webSocketOptions = new WebSocketOptions()
            {
                KeepAliveInterval = TimeSpan.FromSeconds(120),
            };
            app.UseWebSockets(webSocketOptions);
            app.Use(async (context, next) =>
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    using (IServiceScope scope = app.ApplicationServices.CreateScope())
                    {
                        //do something 
                        WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                        await Echo(context, webSocket);
                    }
                }
                else
                {
                    //Hand over to the next middleware
                    await next();
                }
            });

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

        private async Task Echo(HttpContext context, WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];
            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            while (!result.CloseStatus.HasValue)
            {
                await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);

                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            }
            await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
        }
    }
}

NET 6
Program.cs


//加入WebSocket處理服務
builder.Services.AddSingleton<WebSocketHandler>();

#region WebSocket 方式1
app.UseWebSockets();
app.UseMiddleware<WebSocketHandler>();
#endregion

#region WebSocket 方式2
//加入 WebSocket 功能
app.UseWebSockets(new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromSeconds(30)
});

// Middleware 处理
app.Use(async (context, next) =>
{
    if (context.Request.Path == "/ws")
    {
        if (context.WebSockets.IsWebSocketRequest)
        {
            using (WebSocket ws = await context.WebSockets.AcceptWebSocketAsync())
            {
                var wsHandler = context.RequestServices.GetRequiredService<WebSocketHandler>();
                await wsHandler.ProcessWebSocket(ws);
            }
        }
        else
            context.Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
    }
    else await next();
});
#endregion

WebSocketHandler.cs

using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace NurseCall.WebAPI
{
    public class WebSocketHandler
    {
        ConcurrentDictionary<int, WebSocket> WebSockets = new ConcurrentDictionary<int, WebSocket>();
        private readonly ILogger<WebSocketHandler> logger;

        public WebSocketHandler(ILogger<WebSocketHandler> logger)
        {
            this.logger = logger;
        }

        public async Task ProcessWebSocket(WebSocket webSocket)
        {
            WebSockets.TryAdd(webSocket.GetHashCode(), webSocket);
            var buffer = new byte[1024 * 4];
            var res = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            var userName = "anonymous";
            while (!res.CloseStatus.HasValue)
            {
                var cmd = Encoding.UTF8.GetString(buffer, 0, res.Count);
                if (!string.IsNullOrEmpty(cmd))
                {
                    logger.LogInformation(cmd);
                    if (cmd.StartsWith("/USER "))
                        userName = cmd.Substring(6);
                    else
                        Broadcast($"{userName}:\t{cmd}");
                }
                res = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            }
            await webSocket.CloseAsync(res.CloseStatus.Value, res.CloseStatusDescription, CancellationToken.None);
            WebSockets.TryRemove(webSocket.GetHashCode(), out var removed);
            Broadcast($"{userName} left the room.");
        }

        public void Broadcast(string message)
        {
            var buff = Encoding.UTF8.GetBytes($"{DateTime.Now:MM-dd HH:mm:ss}\t{message}");
            var data = new ArraySegment<byte>(buff, 0, buff.Length);
            Parallel.ForEach(WebSockets.Values, async (webSocket) =>
            {
                if (webSocket.State == WebSocketState.Open)
                    await webSocket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
            });
        }
    }
}

3、html页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        table {
            border: 0
        }

        .commslog-data {
            font-family: Consolas, Courier New, Courier, monospace;
        }

        .commslog-server {
            background-color: red;
            color: white
        }

        .commslog-client {
            background-color: green;
            color: white
        }
    </style>
</head>
<body>
    <h1>WebSocket测试页</h1>
    <p id="stateLabel">准备连接...</p>
    <div>
        <label for="connectionUrl">WebSocket服务器URL:</label>
        <input id="connectionUrl" />
        <button id="connectButton" type="submit">连接</button>
    </div>
    <div>
        <label for="sendMessage">消息发送:</label>
        <input id="sendMessage" disabled />
        <button id="sendButton" type="submit" disabled>发送</button>
        <button id="closeButton" disabled>关闭Socket</button>
    </div>

    <p>注意:当连接到默认服务器(即地址栏中的服务器;)时,消息“ ServerClose”将导致服务器关闭连接。同样,消息“ ServerAbort”将导致服务器在不关闭握手的情况下强行终止连接</p>

    <h2>通讯日志</h2>
    <table style="width: 800px">
        <thead>
            <tr>
                <td style="width: 100px">发送</td>
                <td style="width: 100px">接收</td>
                <td>数据</td>
            </tr>
        </thead>
        <tbody id="commsLog"></tbody>
    </table>

    <script>
        var connectionUrl = document.getElementById("connectionUrl");
        var connectButton = document.getElementById("connectButton");
        var stateLabel = document.getElementById("stateLabel");
        var sendMessage = document.getElementById("sendMessage");
        var sendButton = document.getElementById("sendButton");
        var commsLog = document.getElementById("commsLog");
        var socket;
        var scheme = document.location.protocol == "https:" ? "wss" : "ws";
        var port = document.location.port ? (":" + document.location.port) : "";
        connectionUrl.value = scheme + "://" + document.location.hostname + port;
        function updateState() {
            function disable() {
                sendMessage.disabled = true;
                sendButton.disabled = true;
                closeButton.disabled = true;
            }
            function enable() {
                sendMessage.disabled = false;
                sendButton.disabled = false;
                closeButton.disabled = false;
            }
            connectionUrl.disabled = true;
            connectButton.disabled = true;
            if (!socket) {
                disable();
            } else {
                switch (socket.readyState) {
                    case WebSocket.CLOSED:
                        stateLabel.innerHTML = "关闭";
                        disable();
                        connectionUrl.disabled = false;
                        connectButton.disabled = false;
                        break;
                    case WebSocket.CLOSING:
                        stateLabel.innerHTML = "关闭中...";
                        disable();
                        break;
                    case WebSocket.CONNECTING:
                        stateLabel.innerHTML = "连接中...";
                        disable();
                        break;
                    case WebSocket.OPEN:
                        stateLabel.innerHTML = "打开";
                        enable();
                        break;
                    default:
                        stateLabel.innerHTML = "未知的WebSocket状态: " + socket.readyState;
                        disable();
                        break;
                }
            }
        }
        closeButton.onclick = function () {
            if (!socket || socket.readyState != WebSocket.OPEN) {
                alert("socket没有连接");
            }
            socket.close(1000, "从客户端关闭");
        }
        sendButton.onclick = function () {
            if (!socket || socket.readyState != WebSocket.OPEN) {
                alert("socket未连接");
            }
            var data = sendMessage.value;
            socket.send(data);
            commsLog.innerHTML += '<tr>' +
                '<td class="commslog-client">客户端</td>' +
                '<td class="commslog-server">服务端</td>' +
                '<td class="commslog-data">' + data + '</td>'
            '</tr>';
        }
        connectButton.onclick = function () {
            stateLabel.innerHTML = "连接中";
            socket = new WebSocket(connectionUrl.value);
            socket.onopen = function (event) {
                updateState();
                commsLog.innerHTML += '<tr>' +
                    '<td colspan="3" class="commslog-data">连接已打开</td>' +
                    '</tr>';
            };
            socket.onclose = function (event) {
                updateState();
                commsLog.innerHTML += '<tr>' +
                    '<td colspan="3" class="commslog-data">Connection closed. Code: ' + event.code + '. Reason: ' + event.reason + '</td>' +
                    '</tr>';
            };
            socket.onerror = updateState;
            socket.onmessage = function (event) {
                commsLog.innerHTML += '<tr>' +
                    '<td class="commslog-server">服务端</td>' +
                    '<td class="commslog-client">客户端</td>' +
                    '<td class="commslog-data">' + event.data + '</td>'
                '</tr>';
            };
        };
    </script>
</body>
</html>

*

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
.NET Core是微软推出的跨平台开发框架,它支持使用C#等语言进行开发。WebSocket是一种在Web应用程序中实现实时通信的协议。在.NET Core中,可以利用WebSocket类来实现WebSocket通信。下面是一个简单的.NET Core WebSocket类示例: 首先,在Startup.cs中配置WebSocket中间件: ```C# public void ConfigureServices(IServiceCollection services) { // 省略其他配置 services.AddWebSocketManager(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 省略其他配置 app.UseWebSockets(); app.MapWebSocketManager("/ws", app.ApplicationServices.GetService<ChatRoomManager>()); } ``` 然后,创建一个WebSocket处理程序: ```C# public class WebSocketHandler { private readonly WebSocketManager _webSocketManager; public WebSocketHandler(WebSocketManager webSocketManager) { _webSocketManager = webSocketManager; } public async Task Handle(WebSocket socket) { // 处理WebSocket连接 } } ``` 接着,在WebSocket管理器中管理WebSocket连接: ```C# public class WebSocketManager { private readonly ConcurrentDictionary<string, WebSocket> _sockets = new ConcurrentDictionary<string, WebSocket>(); public WebSocket GetSocketById(string id) { // 根据id获取WebSocket连接 } public IEnumerable<WebSocket> GetSockets() { // 获取所有WebSocket连接 } } ``` 最后,在Controller中处理WebSocket请求: ```C# public class WebSocketController : Controller { private readonly WebSocketManager _webSocketManager; public WebSocketController(WebSocketManager webSocketManager) { _webSocketManager = webSocketManager; } [HttpGet("/ws")] public async Task Get() { // 处理WebSocket请求 } } ``` 通过以上示例,可以看到在.NET Core中使用WebSocket类实现了WebSocket通信的基本操作,包括配置中间件、创建处理程序、管理连接和处理请求等。这样就可以在.NET Core应用程序中方便地实现WebSocket实时通信了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值