C#使用WebSocket与网页实时通信的实现示例

首先,要使用WebSocket与网页实时通信,需要在C#时编写WebSocket服务端,并在网页中使用JavaScript编写WebSocket客户端。下面是实现该功能的完整攻略:

C# WebSocket服务端

  1. 创建新项目。在Visual Studio里新建一个Class Library项目。
  2. 安装Newtonsoft.Json NuGet包。在项目中右击References,选择Manage NuGet Packages,搜索安装Newtonsoft.Json。
  3. 创建WebSocket服务端。在项目内新建一个类,命名为WebSocketServer,继承自Microsoft.Web.WebSockets.WebSocketHandler。
  4. 实现WebSocketServer。在WebSocketServer中,重写OnOpen、OnMessage、OnClose方法,实现WebSocket的开启、接收信息、关闭等操作。代码如下:
using Microsoft.Web.WebSockets;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace CSharpWebSocketServer
{
    public class WebSocketServer : WebSocketHandler
    {
        private static List<WebSocketServer> _webSocketServers = new List<WebSocketServer>();

        private string _clientId;

        public WebSocketServer(string clientId)
        {
            _clientId = clientId;

            //将WebSocketServer实例添加到_webSocketServers列表中
            _webSocketServers.Add(this);
        }

        //发送信息
        private async Task SendMessage(string message)
        {
            if (this.WebSocket != null &&
                this.WebSocket.State == WebSocketState.Open)
            {
                //将message传入到客户端中
                await this.WebSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(message)),
                    WebSocketMessageType.Text, true, System.Threading.CancellationToken.None);
            }
        }

        //广播信息
        private static async Task BroadcastMessage(string message)
        {
            var copy = _webSocketServers.ToList();

            foreach (var webSocketServer in copy)
            {
                await webSocketServer.SendMessage(message);
            }
        }

        //WebSocket开启
        public override void OnOpen()
        {
            //跟客户端确认连接已建立,否则连接将会断开
            var authenticationString = Context.Headers["Sec-WebSocket-Key"] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            var bytes = Encoding.UTF8.GetBytes(authenticationString);
            var sha1 = SHA1.Create();
            var hash = sha1.ComputeHash(bytes);
            var response = Convert.ToBase64String(hash);
            this.WebSocket.Send($"HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {response}\r\n\r\n");
        }

        //WebSocket接收信息
        public override void OnMessage(string message)
        {
            //广播信息
            BroadcastMessage(message);
        }

        //WebSocket断开
        public override void OnClose()
        {
            //将WebSocketServer实例从_webSocketServers列表中移除
            _webSocketServers.Remove(this);
            //广播离开信息
            var leaveMessage = new { Type = "leave", Id = _clientId };
            BroadcastMessage(JsonConvert.SerializeObject(leaveMessage));
        }
    }
}
  1. 创建WebSocket服务端主程序。在项目内新建一个类,命名为Program,定义Main方法。在Main方法中,实例化一个HttpListenerWrapper,并利用HttpListenerWrapper启动WebSocket服务端。代码如下:
using System;
using System.Threading.Tasks;

namespace CSharpWebSocketServer
{
    class Program
    {
        static void Main(string[] args)
        {
            var httpListenerWrapper = new HttpListenerWrapper();
            httpListenerWrapper.Start();

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }

    public class HttpListenerWrapper
    {
        // WebSocket请求的地址
        const string ListenerAddress = "http://localhost:8888/realtime";

        internal void Start()
        {
            using (var listener = new System.Net.HttpListener())
            {
                listener.Prefixes.Add(ListenerAddress + "/");
                listener.Start();

                Console.WriteLine($"开始监听地址{ListenerAddress}");

                while (true)
                {
                    var context = listener.GetContextAsync().Result;
                    if (context.Request.IsWebSocketRequest)
                    {
                        AcceptWebSocketAsync(context).Wait();
                    }
                }
            }
        }

        async Task AcceptWebSocketAsync(System.Net.HttpListenerContext context)
        {
            if (context.Request.IsWebSocketRequest)
            {
                var subProtocol = context.Request.Headers["Sec-WebSocket-Protocol"];
                var webSocketContext = await context.AcceptWebSocketAsync(subProtocol);

                var clientId = Guid.NewGuid().ToString();
                var webSocketServer = new WebSocketServer(clientId);
                webSocketServer.WebSocket = webSocketContext.WebSocket;

                Console.WriteLine($"客户端{clientId}已连接");

                await webSocketServer.OnOpenAsync();

                while (webSocketServer.WebSocket.State == WebSocketState.Open)
                {
                    var message = string.Empty;
                    var buffer = new byte[4096];
                    var result = await webSocketServer.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), System.Threading.CancellationToken.None);

                    if (result.MessageType == WebSocketMessageType.Text)
                    {
                        message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    }
                    else if (result.MessageType == WebSocketMessageType.Binary)
                    {
                        Console.WriteLine("Binary messages are not supported");
                    }

                    await webSocketServer.OnMessageAsync(message);
                }

                await webSocketServer.OnCloseAsync(null);
            }
        }
    }
}

JavaScript WebSocket客户端

在网页中使用JavaScript的WebSocket API与WebSocket服务端进行通信。下面是一个基于WebSocket的聊天室的示例:

  1. 创建HTML文件。在HTML文件中添加一个input、一个button和一个div元素,用来输入信息和显示聊天记录。代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Chat Room</title>
</head>
<body>
    <div id="logs"></div>

    <input type="text" id="input-text">
    <button id="btn-send">Send</button>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="chat.js"></script>
</body>
</html>
  1. 创建JavaScript文件。在JavaScript文件中,先定义一些初始值,如WebSocket服务端地址、WebSocket对象、客户端ID等。然后,绑定button的点击事件,在事件处理程序中,获取输入框的信息,发送到WebSocket服务端,并将信息显示在页面上。代码如下:
$(function () {
    var wsUrl = 'ws://localhost:8888/realtime';
    var socket;
    var clientId;

    socket = new WebSocket(wsUrl);

    //接收到WebSocket服务端的消息
    socket.onmessage = function (evt) {
        var message = JSON.parse(evt.data);

        switch (message.Type) {
            //有人加入聊天室
            case "join":
                $('#logs').append('<div>' + message.Username + ' joined the chat.</div>');
                break;
            //有人发消息
            case "message":
                $('#logs').append('<div>' + message.Username + ': ' + message.Content + '</div>');
                break;
            //有人离开聊天室
            case "leave":
                $('#logs').append('<div>' + message.Id + ' left the chat.</div>');
                break;
        }

        $('#logs').scrollTop($('#logs')[0].scrollHeight - $('#logs').height());
    };

    //WebSocket服务端连接已打开
    socket.onopen = function (evt) {
        clientId = generateClientId();
        var joinMessage = { Type: "join", Username: clientId };
        socket.send(JSON.stringify(joinMessage));
    };

    //WebSocket服务端连接已关闭
    socket.onclose = function (evt) {
        console.log('WebSocket closed.');
    };

    //WebSocket服务端连接出错
    socket.onerror = function (evt) {
        console.log('WebSocket error.');
    };

    //绑定"Send"按钮点击事件
    $('#btn-send').on('click', function () {
        var inputText = $('#input-text').val();
        $('#input-text').val('');
        var message = { Type: "message", Username: clientId, Content: inputText };
        socket.send(JSON.stringify(message));
        $('#logs').append('<div>Me: ' + inputText + '</div>');
    });

    //生成客户端ID
    function generateClientId() {
        var d = new Date().getTime();
        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }
        var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
        return uuid;
    }
});

以上就是使用WebSocket实现网页实时通信的完整攻略。除了以上的聊天室示例,还可以使用WebSocket实现更多的实时交互功能,如赛事直播、在线游戏等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#使用WebSocket与网页实时通信的实现示例 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • 微信小程序与AspNetCore SignalR聊天实例代码

    微信小程序与AspNetCore SignalR聊天实例代码 在本攻略中,我们将详细讲解如何使用微信小程序和AspNetCore SignalR实现聊天功能,并提供两个示例说明。 步骤一:创建AspNetCore SignalR应用程序 首先,我们需要创建一个AspNetCore SignalR应用程序。您可以使用Visual Studio创建一个新的Asp…

    C# 2023年5月17日
    00
  • C#实现聊天消息渲染与图文混排详解

    C#实现聊天消息渲染与图文混排详解 在 C# 中,我们可以使用 WinForms 或 WPF 来实现聊天消息渲染和图文混排。本攻略将介绍如何使用 WinForms 或 WPF 实现聊天消息渲染和图文混排,并提供两个示例说明。 WinForms 实现 步骤1:创建 WinForms 应用程序 首先,我们需要创建一个 WinForms 应用程序。可以使用 Vis…

    C# 2023年5月17日
    00
  • 一步步打造简单的MVC电商网站BooksStore(3)

    一步步打造简单的MVC电商网站BooksStore(3) 在这一部分中,我们将继续完善我们的MVC电商网站开发计划,包括:数据库设计,模型开发和控制器开发。 数据库设计 在我们的电商网站开发中,我们将使用MySQL数据库来存储数据。我们需要设计一些数据表来存储用户信息、产品信息、订单信息等。 具体来说,我们需要至少设计三个表:一个用户信息表,一个产品信息表和…

    C# 2023年5月31日
    00
  • C#中var关键字用法分析

    C#中var关键字用法分析 在C#中,var关键字可用于声明一个隐式类型的变量,这种类型是在编译器编译时推断出来的。在这篇文章中,我们将详细讲解var关键字的用法,并给出示例说明。 var的用法 1. 声明变量 使用var来声明一个变量时,编译器会自动将该变量的类型推断为其初始化表达式的类型。 var name = "Tom"; var …

    C# 2023年6月1日
    00
  • C#向无窗口的进程发送消息

    下面是详细的讲解。 C#向无窗口的进程发送消息的完整攻略 在C#中,我们可以使用Windows API来向无窗口的进程发送消息。下面是完整的攻略。 1. 准备工作 要向无窗口的进程发送消息,我们需要知道目标进程的进程ID(PID)。可以使用Windows API中的Process.GetProcessesByName()方法获取指定名称的进程列表,然后根据需…

    C# 2023年6月6日
    00
  • C#中的委托和事件

    委托和事件的概念说明: 委托是一种类型,代表可以指向具有特定参数列表和返回类型的方法的引用,可以使方法的参数自由变化,可以做到比直接调用方法更灵活。 事件是一种特殊的委托,被用于实现发布者/订阅者模式,通过事件的注册和触发可以完成对象间的通信。 委托的声明和使用: 声明委托的语法:delegate returnType DelegateName(parame…

    C# 2023年5月15日
    00
  • XUnit数据共享与并行测试

    引言 在单元或者集成测试的过程中,需要测试的用例非常多,如果测试是一条一条过,那么需要花费不少的时间。从 V2 开始,默认情况下 XUnit 自动配置并行(参考资料),大大提升了测试速度。本文将对 ASP.NET CORE WEBAPI 程序进行集成测试,并探讨 XUnit 的数据共享与测试并行的方法。 XUnit默认在一个类内的测试代码是串行执行的,而在不…

    C# 2023年5月10日
    00
  • C#泛型的使用及示例详解

    C#泛型的使用及示例详解 什么是泛型 泛型是C#中的一个重要特性,它将类型参数化,从而实现了代码的复用性和类型安全。 将值类型和引用类型参数化,使得在编写代码时可以将类型作为参数来传递,从而使代码更加通用化和可扩展。而且,由于泛型是在编译时进行类型检查的,所以可以避免一些类型转换的错误。 泛型的语法 泛型的语法格式是: class Name<T>…

    C# 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部