.net websocket 使用

系列文章目录

目录

文章目录

前言

一、websocket是什么?

一、工作原理

二、特点与优势

三、应用场景

四、缺点与挑战

二、使用步骤

1.引入库

2.如何使用

总结


文章目录


前言

WebSocket是一种网络通信协议,旨在解决传统HTTP协议在实时通信方面的不足。


一、websocket是什么?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。它允许客户端与服务器之间进行持久的、双向的通信,而无需像传统HTTP那样需要客户端不断发起请求来检查服务器是否有新数据。WebSocket协议在2008年首次提出,2011年被IETF(互联网工程任务组)作为标准RFC 6455发布,并由W3C(万维网联盟)进行标准化。

一、工作原理

WebSocket的工作原理可以分为三个阶段:握手、数据传输和断开连接。

  1. 握手 :客户端通过发送一个特殊的HTTP请求头来向服务器发起WebSocket连接请求。这个请求中包含了一些特定的字段,如UpgradeConnectionSec-WebSocket-Key等,用于表明客户端希望将协议从HTTP升级到WebSocket。服务器在接收到这个请求后,会进行验证,并返回一个包含Sec-WebSocket-Accept字段的HTTP响应头,表示握手成功,双方建立了WebSocket连接。
  2. 数据传输:一旦建立了WebSocket连接,客户端和服务器就可以通过该连接进行双向的实时数据传输。数据以帧的形式进行传输,每个帧都包含了一些特定的字段,如FIN(表示该帧是否是消息的最后一帧)、Opcode(指定该帧的类型,如文本帧或二进制帧)、Mask(表示是否对数据进行了掩码处理)、Payload Length(数据的长度)以及Payload Data(实际发送的数据)。
  3. 断开连接:当连接不再需要时,客户端或服务器可以发起关闭连接的请求。双方会交换特殊的关闭帧,以协商关闭连接,并确保双方都接收到了关闭请求。

二、特点与优势

  1. 全双工通信:与传统HTTP请求/响应模式不同,WebSocket可以同时进行发送和接收数据。这意味着服务器可以主动向客户端发送数据,而不需要客户端先发起请求。
  2. 低延迟:由于建立了持久连接,并且数据传输没有额外的HTTP头部信息负担,因此WebSocket能够更快地传输小量数据。
  3. 节省带宽:WebSocket只需要一个TCP握手就能创建一个到服务器的链接,并且这个链接可以被复用以节省带宽。
  4. 跨域问题简单:在正确配置后,WebSocket允许跨域通讯。
  5. 适用于实时应用:对于聊天、游戏、实时交易等实时性要求高的应用,WebSocket能够提供更好的服务。

三、应用场景

WebSocket在实际应用中具有广泛的应用场景,包括但不限于:

  1. 实时聊天应用:如在线聊天室、即时通讯软件等,用户可以实时地发送和接收消息,提高了沟通效率。
  2. 在线游戏:实现游戏数据的实时传输和同步,为玩家提供更好的游戏体验。
  3. 实时数据监控:如股票价格、天气信息、交通状况等,服务器可以实时地将最新的数据推送给客户端。
  4. 协同办公:如在线文档编辑、实时会议等,多个用户可以同时编辑同一个文档或代码文件,他们的编辑结果会实时地同步到其他用户的界面上。
  5. 物联网(IoT):用于设备的远程监控和控制,允许实时收集和传输设备数据。

四、缺点与挑战

尽管WebSocket具有诸多优势,但也存在一些缺点和挑战:

  1. 兼容性问题:虽然大多数现代浏览器都支持WebSocket,但是一些老版本浏览器可能不支持。此外,一些网络代理和防火墙可能会阻止WebSocket连接。
  2. 安全性问题:WebSocket虽然在协议上支持加密(如WSS,即加密的WebSocket),但它并没有像HTTP那样有完善成熟的安全策略。开发者需要自己去处理安全性问题,如校验消息内容等。
  3. 服务器压力较高:由于需要保持长连接,所以会占用较多的服务器资源。这对服务器的性能和管理提出了更高的要求。
  4. 不适合大数据量传输:WebSocket更适合频繁、小数据量传输。对于大文件或大数据量传输来说,可能并不是最理想的选择。

综上所述,WebSocket作为一种现代Web实时通信的核心技术,具有显著的优势和广泛的应用场景。然而,在使用WebSocket时也需要考虑其兼容性问题、安全性问题以及服务器资源管理等挑战。

二、使用步骤

1.引入库

代码如下(示例):

cs 复制代码
using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.WebSockets;

2.如何使用

1.新建帮助类

代码如下(示例):

cs 复制代码
using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.WebSockets;

namespace Xhxx.WebSockets;

public class WebSocketHandler
{
    private WebSocket _webSocket;

    private int frameBytesCount = 10240;

    public event EventHandler Opened;

    public event EventHandler<string> TextMessageReceived;

    public event EventHandler Closed;

    public virtual async Task ProcessRequest(AspNetWebSocketContext context)
    {
        _webSocket = context.WebSocket;
        RaiseOpenEvent();
        while (_webSocket.State == WebSocketState.Open)
        {
            List<byte> receivedBytes = new List<byte>();
            ArraySegment<byte> buffer2 = WebSocket.CreateServerBuffer(frameBytesCount);
            WebSocketReceiveResult receiveResult = await _webSocket.ReceiveAsync(buffer2, CancellationToken.None);
            if (receiveResult.MessageType == WebSocketMessageType.Close)
            {
                await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
                RaiseOnClosed();
                break;
            }

            WebSocketMessageType messageType = receiveResult.MessageType;
            MergeFrameContent(receivedBytes, buffer2.Array, receiveResult.Count);
            while (!receiveResult.EndOfMessage)
            {
                buffer2 = WebSocket.CreateServerBuffer(frameBytesCount);
                receiveResult = await _webSocket.ReceiveAsync(buffer2, CancellationToken.None);
                MergeFrameContent(receivedBytes, buffer2.Array, receiveResult.Count);
            }

            RaiseMessageArrive(receivedBytes.ToArray(), messageType, receivedBytes.Count);
        }
    }

    public virtual async Task SendMessage(string message)
    {
        if (_webSocket == null || _webSocket.State != WebSocketState.Open)
        {
            throw new InvalidOperationException("the web socket is not open.");
        }

        byte[] bytes = Encoding.UTF8.GetBytes(message);
        for (int sentBytes = 0; sentBytes < bytes.Length; sentBytes += frameBytesCount)
        {
            int remainingBytes = bytes.Length - sentBytes;
            await _webSocket.SendAsync(new ArraySegment<byte>(bytes, sentBytes, (remainingBytes > frameBytesCount) ? frameBytesCount : remainingBytes), WebSocketMessageType.Text, endOfMessage: true, CancellationToken.None);
        }
    }

    protected void MergeFrameContent(List<byte> destBuffer, byte[] buffer, long count)
    {
        count = ((count < buffer.Length) ? count : buffer.Length);
        if (count == buffer.Length)
        {
            destBuffer.AddRange(buffer);
            return;
        }

        byte[] array = new byte[count];
        Array.Copy(buffer, array, count);
        destBuffer.AddRange(array);
    }

    protected void RaiseOpenEvent()
    {
        this.Opened?.Invoke(this, EventArgs.Empty);
    }

    protected void RaiseMessageArrive(byte[] buffer, WebSocketMessageType type, long count)
    {
        if (type == WebSocketMessageType.Text && this.TextMessageReceived != null)
        {
            this.TextMessageReceived(this, Encoding.UTF8.GetString(buffer));
        }
    }

    protected void RaiseOnClosed()
    {
        this.Closed?.Invoke(this, EventArgs.Empty);
    }
}

2使用帮助类

cs 复制代码
      private static Dictionary<string, WebSocketHandler> _handlers = new Dictionary<string, WebSocketHandler>();
public HttpResponseMessage Connect(string nickName)
{
    var webSocketHandler = new WebSocketHandler();
    if (_handlers.ContainsKey(nickName))
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
    _handlers[nickName] = webSocketHandler;
    webSocketHandler.TextMessageReceived += (sendor, Parameter) =>
    {
        try
        {
            WebSocketDto _para = Newtonsoft.Json.JsonConvert.DeserializeObject<WebSocketDto>(Parameter);
            if (_para == null)
            {
                _handlers.Remove(nickName);
                result.code = (int)Const.c_code.参数错误;
                result.message = Const.c_code.参数错误.ToString();
                SendMessage(nickName, result.ToJson());
            }
            else
            {
                _para.nickName = nickName;
                if (_para.queryType == (int)QuestType.Login)
                {
                    DealMainLogin(_para);
                }
                if (_para.queryType == (int)QuestType.Agent)
                {
                    DealMainAgent(_para);
                }
                if (_para.queryType == (int)QuestType.xintiao)
                {
                    result.code = (int)QuestType.xintiao;
                    result.message = "恭喜,您目前处于活蹦乱跳状态 ^_^ ";
                    SendMessage(nickName, result.ToJson());
                }
            }
        }
        catch (Exception ex)
        {
            _handlers.Remove(nickName);
            result.code = (int)Const.c_code.抛出异常;
            result.message = ex.Message;
            SendMessage(nickName, result.ToJson());
        }
    };
    webSocketHandler.Closed += (sendor, arg) =>
    {
        if (nickName.Contains("login_"))
        {
            ClosedLogin(nickName);
        }
        _handlers.Remove(nickName);
    };
    webSocketHandler.Opened += (sendor, arg) =>
    {
        result.message = "连接成功...";
        SendMessage(nickName, result.ToJson());
    };

    HttpContext.Current.AcceptWebSocketRequest(webSocketHandler);

    return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
}

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sendorNickName"></param>
        /// <param name="message"></param>
        private void SendMessage(string sendorNickName, string message, bool Broadcast = false)
        {
            foreach (var handlerKvp in _handlers)
            {
                if (Broadcast)
                {
                    //广播发送
                    handlerKvp.Value.SendMessage(message).Wait();
                }
                else
                {
                    //点对点发送
                    if (handlerKvp.Key == sendorNickName)
                    {
                        handlerKvp.Value.SendMessage(message).Wait();
                    }
                }

            }
        }

总结

这就是相关的websocket 使用方法

相关推荐
玩泥巴的9 小时前
飞书 .NET SDK 事件处理的幂等性与去重机制
c#·.net·二次开发·飞书
sunfove9 小时前
光网络的立交桥:光开关 (Optical Switch) 原理与主流技术解析
网络
喵叔哟10 小时前
20.部署与运维
运维·docker·容器·.net
Kevin Wang72712 小时前
欧拉系统服务部署注意事项
网络·windows
min18112345612 小时前
深度伪造内容的检测与溯源技术
大数据·网络·人工智能
汤愈韬12 小时前
NAT策略
网络协议·网络安全·security·huawei
汤愈韬12 小时前
Full Cone Nat
网络·网络协议·网络安全·security·huawei
今晚务必早点睡13 小时前
系统通信方式实战详解:HTTP、RPC、MQ、WebSocket 各用在什么场景?(附 SDK 示例)
websocket·http·rpc
zbtlink13 小时前
现在还需要带电池的路由器吗?是用来干嘛的?
网络·智能路由器
桌面运维家13 小时前
vDisk配置漂移怎么办?VOI/IDV架构故障快速修复
网络·架构