基于NetCoreServer的WebSocket客户端实现群播(学习笔记)

一、NetCoreServer介绍

超快速、低延迟的异步套接字服务器和客户端 C# .NET Core 库,支持 TCP、SSL、UDP、HTTP、HTTPS、WebSocket 协议和 10K 连接问题解决方案。
客户端
开源地址:https://github.com/chronoxor/NetCoreServer
支持:
Example: TCP chat server
Example: TCP chat client
Example: SSL chat server
Example: SSL chat client
Example: UDP echo server
Example: UDP echo client
Example: UDP multicast server
Example: UDP multicast client
Example: Unix Domain Socket chat server
Example: Unix Domain Socket chat client
Example: Simple protocol
Example: Simple protocol server
Example: Simple protocol client
Example: HTTP server
Example: HTTP client
Example: HTTPS server
Example: HTTPS client
Example: WebSocket chat server
Example: WebSocket chat client
Example: WebSocket secure chat server
Example: WebSocket secure chat client
本文重点学习WebSocket通讯

二、服务端及双客户端代码

在这里插入图片描述

2.1 服务端控制台

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using NetCoreServer;namespace WsChatServer
{class ChatSession : WsSession{public ChatSession(WsServer server) : base(server) {}public override void OnWsConnected(HttpRequest request){Console.WriteLine($"Chat WebSocket session with Id {Id} connected!");// Send invite messagestring message = "Hello from WebSocket chat! Please send a message or '!' to disconnect the client!";SendTextAsync(message);}public override void OnWsDisconnected(){Console.WriteLine($"Chat WebSocket session with Id {Id} 已断开!");}public override void OnWsReceived(byte[] buffer, long offset, long size){string message = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);Console.WriteLine("来自: " + message);// Multicast message to all connected sessions((WsServer)Server).MulticastText(message);// If the buffer starts with '!' the disconnect the current sessionif (message == "!")Close();}protected override void OnError(SocketError error){Console.WriteLine($"Chat WebSocket session caught an error with code {error}");}}class ChatServer : WsServer{public ChatServer(IPAddress address, int port) : base(address, port) {}protected override TcpSession CreateSession() { return new ChatSession(this); }protected override void OnError(SocketError error){Console.WriteLine($"错误 {error}");}}class Program{static void Main(string[] args){// WebSocket server port 服务端口int port = 9999;if (args.Length > 0)port = int.Parse(args[0]);// WebSocket server content pathstring www = "../../../../../www/ws";if (args.Length > 1)www = args[1];Console.WriteLine($"WebSocket 服务端口: {port}");Console.WriteLine($"WebSocket server static content path: {www}");Console.WriteLine($"WebSocket server website: http://localhost:{port}/chat/index.html");Console.WriteLine();// Create a new WebSocket servervar server = new ChatServer(IPAddress.Any, port);server.AddStaticContent(www, "/chat");// Start the serverConsole.Write("服务端启动...");server.Start();Console.WriteLine("完成!");Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");// Perform text inputfor (;;){string line = Console.ReadLine();//接受输入if (string.IsNullOrEmpty(line))break;// Restart the serverif (line == "!"){//重启标识!Console.Write("Server restarting...");server.Restart();Console.WriteLine("Done!");}// Multicast admin message to all sessionsline = "[管理员] " + line;   //前缀admin管理员消息server.MulticastText(line);//广播}// Stop the serverConsole.Write("服务端停止...");server.Stop();Console.WriteLine("完成!");}}
}

2.2 客户端html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>WebSocket聊天客户端示例</title><link rel="icon" type="image/png" href="./favicon.png"/>
</head>
<body><script>var myname;var isconned=false;//初始化function init(){document.myform.url.value = "ws://localhost:9999/"//不要和系统的端口冲突document.myform.inputtext.value = "Hello World!"//问候语document.myform.disconnectButton.disabled = true//断开连接默认禁用}
//打开连接function doConnect(){isconned=true;websocket = new WebSocket(document.myform.url.value)websocket.onopen = function(evt) { onOpen(evt) }websocket.onclose = function(evt) { onClose(evt) }websocket.onmessage = function(evt) { onMessage(evt) }websocket.onerror = function(evt) { onError(evt) }}
//打开function onOpen(evt){writeToScreen("connected\n")document.myform.connectButton.disabled = truedocument.myform.disconnectButton.disabled = falsemyname=document.myform.myname.value}
//关闭function onClose(evt){writeToScreen("disconnected\n")document.myform.connectButton.disabled = falsedocument.myform.disconnectButton.disabled = true}
//发消息function onMessage(evt){writeToScreen("接收<<" + evt.data + '\n')}
//错误function onError(evt){writeToScreen('error: ' + evt.data + '\n')websocket.close()//关闭websocketdocument.myform.connectButton.disabled = false//启用连接document.myform.disconnectButton.disabled = true//断开禁用}
//发送消息function doSend(message){writeToScreen("发送>>" + message + '\n')//回显websocket.send(message)//发送到服务端}
//输出到屏幕function writeToScreen(message){document.myform.outputtext.value += message//拼接document.myform.outputtext.scrollTop = document.myform.outputtext.scrollHeight//滚动到底部}
//监听window.addEventListener("load", init, false)
//发送方法function sendText(){var msg=document.myform.inputtext.value;if(msg==""||isconned==false){alert("对不起,请输入内容或先连接");return;}doSend("["+myname+"] "+msg)//消息内容}
//清屏function clearText(){document.myform.outputtext.value = ""}
//断开连接function doDisconnect(){isconned=false;websocket.close()}</script><h3>WebSocket Client</h3><form name="myform"><p><li>姓名:<input name="myname" value="X5ZJ" class="txt" /><li><li>地址:<input name="url" class="txt"/></li><li><input type="button" name=connectButton value="连接" onClick="doConnect()"><input type="button" name=disconnectButton value="断开" onClick="doDisconnect()"></li></p><p><textarea name="outputtext" cols="35" rows="10" readonly>聊天记录</textarea></p><p>内容:<input name="inputtext" class="txt"/></p><p><input type="button" name=sendButton value="发送" onClick="sendText()"><input type="button" name=clearButton value="清屏" onClick="clearText()"></p></form><style>p{line-height:20px;padding:4px}.txt{width:200px}li{list-style-type:none;margin:2px}</style>
</body>
</html>

2.3 客户端控制台

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using NetCoreServer;namespace WsChatClient
{class ChatClient : WsClient{public ChatClient(string address, int port) : base(address, port) {}public void DisconnectAndStop(){_stop = true;CloseAsync(1000);while (IsConnected)Thread.Yield();}public override void OnWsConnecting(HttpRequest request){request.SetBegin("GET", "/");request.SetHeader("Host", "localhost");request.SetHeader("Origin", "http://localhost");request.SetHeader("Upgrade", "websocket");request.SetHeader("Connection", "Upgrade");request.SetHeader("Sec-WebSocket-Key", Convert.ToBase64String(WsNonce));request.SetHeader("Sec-WebSocket-Protocol", "chat, superchat");request.SetHeader("Sec-WebSocket-Version", "13");request.SetBody();}public override void OnWsConnected(HttpResponse response){Console.WriteLine($"Chat WebSocket client connected a new session with Id {Id}");}public override void OnWsDisconnected(){Console.WriteLine($"Chat WebSocket client disconnected a session with Id {Id}");}public override void OnWsReceived(byte[] buffer, long offset, long size){Console.WriteLine($"Incoming: {Encoding.UTF8.GetString(buffer, (int)offset, (int)size)}");}protected override void OnDisconnected(){base.OnDisconnected();Console.WriteLine($"Chat WebSocket client disconnected a session with Id {Id}");// Wait for a while...Thread.Sleep(1000);// Try to connect againif (!_stop)ConnectAsync();}protected override void OnError(SocketError error){Console.WriteLine($"Chat WebSocket client caught an error with code {error}");}private bool _stop;}class Program{static void Main(string[] args){// WebSocket server addressstring address = "127.0.0.1";if (args.Length > 0)address = args[0];// WebSocket server port 服务端口一致 9999int port = 9999;if (args.Length > 1)port = int.Parse(args[1]);Console.WriteLine($"WebSocket server address: {address}");Console.WriteLine($"WebSocket server port: {port}");Console.WriteLine();// Create a new TCP chat clientvar client = new ChatClient(address, port);// Connect the clientConsole.Write("Client connecting...");client.ConnectAsync();//连接Console.WriteLine("Done!");Console.WriteLine("Press Enter to stop the client or '!' to reconnect the client...");//获取Guid值作为随机数种子string guid = System.Guid.NewGuid().ToString();Random random = new Random(guid.GetHashCode());string IdPart = random.Next(10000, 99999).ToString();// Perform text inputfor (;;){string line = Console.ReadLine();//接受输入if (string.IsNullOrEmpty(line))break;// Disconnect the clientif (line == "!"){//端口连接符!Console.Write(IdPart+"Client disconnecting...");client.SendTextAsync(IdPart+",will be disconnecting...");client.DisconnectAsync();Console.WriteLine("Done!");continue;}// Send the entered text to the chat server 发送内容client.SendTextAsync(string.Format("[{0}] {1} ({2})", IdPart,line,DateTime.Now.ToString("MM-dd HH:mm:ss FFF")));//客户端发送}// Disconnect the clientConsole.Write("Client disconnecting...");client.DisconnectAndStop();//断开Console.WriteLine("Done!");}}
}

客户端可以继续优化实现群聊。注意服务端口和ws地址改成服务器地址即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/285898.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中的代理模式(动态代理和静态代理)

代理模式 我们先了解一下代理模式&#xff1a; 在开发中&#xff0c;当我们要访问目标类时&#xff0c;不是直接访问目标类&#xff0c;而是访问器代理类。通过代理类调用目标类完成操作。简单来说就是&#xff1a;把直接访问变为间接访问。 这样做的最大好处就是&#xff1a…

基于Spring Boot网络相册设计与实现

摘 要 网络相册设计与实现的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&am…

在微信小程序中或UniApp中自定义tabbar实现毛玻璃高斯模糊效果

backdrop-filter: blur(10px); 这一行代码表示将背景进行模糊处理&#xff0c;模糊程度为10像素。这会导致背景内容在这个元素后面呈现模糊效果。 background-color: rgb(255 255 255 / .32); 这一行代码表示设置元素的背景颜色为白色&#xff08;RGB值为0, 0, 0&#xff09;&a…

第八节:深入讲解SMB中的Http组件

一、概述 Http组作是SMB中的核心组件之一&#xff0c;在第七节中讲解了如何简洁的进行web程序部署和运行&#xff0c;这只是它的功能之一。在本节中&#xff0c;我们将介绍Http组件的重要属性。 二、请求头Request 1、支持方法 支持POST、GET、PUT、DELETE、OPTIONS等方法&a…

uniapp ios证书失效

前面是按照网上查找的方法 作者大大的地址 1、一个ios账户&#xff08;688付费版&#xff09; 2、登录 Apple Developer 3、创建Identifiers ps&#xff1a;创建时需继承苹果的sdk&#xff0c;只需要一个就行 点击continue再点击Register即可 4、创建.cer证书 &…

DP:斐波那契数列模型

创作不易&#xff0c;感谢三连支持 &#xff01; 斐波那契数列用于一维探索的单峰函数之中&#xff0c;用于求解最优值的方法。其主要优势为&#xff0c;在第一次迭代的时候求解两个函数值&#xff0c;之后每次迭代只需求解一次 。 一、第N个泰波那契数 . - 力扣&#xff08;…

AnyGo for Mac最新激活版:位置模拟软件打破地域限制

AnyGo for Mac&#xff0c;一款专为Mac用户打造的位置模拟软件&#xff0c;让您能够轻松打破地域限制&#xff0c;畅享无限可能。 软件下载&#xff1a;AnyGo for Mac v7.0.0最新激活版 通过AnyGo&#xff0c;您可以随时随地模拟出任何地理位置&#xff0c;无论是国内热门景点还…

Word2vec学习笔记

&#xff08;1&#xff09;NNLM模型&#xff08;神经网络语言模型&#xff09; 语言模型是一个单纯的、统一的、抽象的形式系统&#xff0c;语言客观事实经过语言模型的描述&#xff0c;比较适合于电子计算机进行自动处理&#xff0c;因而语言模型对于自然语言的信息处理具有重…

【Unity】uDD插件抓屏文字显示不清晰怎么办?

【背景】 之前介绍过用一款简称uDD&#xff08;uDesktopDuplication&#xff09;的开源插件抓取电脑桌面。整体效果不错&#xff0c;看电影很流畅。但是当切换到文档&#xff0c;或者仔细看任何UI的文字部分时&#xff0c;发现就模糊了。 【分析】 由于是依托于Canvas上的Te…

【vue3学习之路(一)】

文章目录 前言一、vue3项目创建1.1环境准备1.1.1 基于 vue-cli 创建&#xff08;脚手架创建&#xff09;1.1.2 基于 vite 创建&#xff08;推荐&#xff09; 二、熟悉流程总结 前言 参考视频&#xff1a;https://www.bilibili.com/video/BV1Za4y1r7KE?p10&spm_id_frompag…

怎么压缩动图的大小?gif图片过大怎么压缩?动图压缩不求人

工作中&#xff0c;大家都可能会遇到处理GIF图片的情况。 比如&#xff1a; 1.网站 网页上如果有一大堆图片&#xff0c;一定要处理动图&#xff08;它容量太大了&#xff09;。 因为这玩意多了很卡&#xff0c;使网页加载速度慢。 2.公众号 公众号上传动图和整篇推文是有…

4.1.1 SN74LVC245A型总线收发器

SN74LVC245A是德州仪器(Texas Instruments)推出的一款集成电路芯片,属于SN74系列。它是一款双向总线驱动器,可用于高速CMOS逻辑电平之间的电平转换。这款芯片可以实现3.3V/5V逻辑电平之间的转换,具有高速和低功耗的特点。SN74LVC245A在电子系统中常用于数据总线的电平转换…

QT_day3:2024/3/22

作业1&#xff1a;设计界面 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin…

Python库xarray:强大的多维数据处理工具

Python库xarray&#xff1a;强大的多维数据处理工具 在数据科学和科学计算领域&#xff0c;处理多维数据是一项常见而重要的任务。Python库xarray是一个功能强大的工具&#xff0c;专门用于处理、分析和可视化多维数据集。本文将深入介绍xarray库的特性、用法和优势&#xff0c…

CSS设置移动端页面底部安全距离

env(safe-area-inset-bottom)是一个CSS属性值&#xff0c;用于设置底部安全距离。它表示使用环境变量来获取底部安全距离的值。当使用环境变量时&#xff0c;需要使用env()函数来引用具体的环境变量。例如&#xff1a; <style> .box{padding-bottom: env(safe-area-inse…

Flutter 3.13 之后如何监听 App 生命周期事件

在 Flutter 中&#xff0c;您可以监听多个生命周期事件来处理应用程序的不同状态&#xff0c;但今天我们将讨论 didChangeAppLifecycleState 事件。每当应用程序的生命周期状态发生变化时&#xff0c;就会触发此事件。可能的状态有 resumed 、 inactive 、 paused 、 detached …

【性能测试】jmeter连接数据库jdbc

一、下载第三方工具包驱动数据库 1. 因为JMeter本身没有提供链接数据库的功能&#xff0c;所以我们需要借助第三方的工具包来实现。 &#xff08;有这个jar包之后&#xff0c;jmeter可以发起jdbc请求&#xff0c;没有这个jar包&#xff0c;也有jdbc取样器&#xff0c;但不能发起…

【智能家居】东胜物联提供软硬一体化智能家居解决方案,助企业提高市场占有率

背景 随着智能家居市场的不断壮大&#xff0c;越来越多的消费者开始享受到它带来的便捷和效益。现在&#xff0c;他们可以通过远程或语音控制设备进行个性化设置&#xff0c;比如调节照明和温度&#xff0c;让生活变得更加舒适和智能化。 根据SPER市场研究&#xff0c;预计秘…

【3D reconstruction 学习笔记】

三维重建 3D reconstruction 1. 相机几何针孔相机摄像机几何 2. 相机标定线性方程组的解齐次线性方程组的解非线性方程组的最小二乘解透镜相机标定带畸变的相机标定 3. 单视图重建2D平面上的变换3D空间上的变换单视测量无穷远点 无穷远线 无穷远平面影消点 影消线单视重构 4. 三…

YOLOv9改进策略:卷积魔改 | SCConv:空间和通道重建卷积,即插即用,助力检测 | CVPR2023

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a; CVPR2023 SCConv 由两个单元组成&#xff1a;空间重建单元&#xff08;SRU&#xff09;和通道重建单元&#xff08;CRU&#xff09;。 SRU利用分离重建方法来抑制空间冗余&#xff0c;而CRU使用分割-变换-融…