基于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.mzph.cn/news/764719.shtml

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

相关文章

34 vue 项目默认暴露出去的 public 文件夹 和 CopyWebpackPlugin

前言 这里说一下 vue.config.js 中的一些 public 文件夹是怎么暴露出去的? 我们常见的 CopyWebpackPlugin 是怎么工作的 ? 这个 也是需要 一点一点积累的, 因为 各种插件 有很多, 不过 我们仅仅需要 明白常见的这些事干什么的即可 当然 以下内容会涉及到一部分vue-cli,…

Vue2(九):尚硅谷TodoList案例(初级版):组件化编码流程的使用

一、组件化编码流程及资料 百度网盘 请输入提取码 提取码yyds &#xff08;Vue全家桶资料&#xff09; 组件化编码流程分为三步&#xff1a; 二、实现静态组件 1、分析结构 确定组件名称&#xff08;Header,List,Item,Footer&#xff09;和个数&#xff0c;还有嵌套关系(…

阿里云服务器租用一年多少钱?2024年最新阿里云租用价格

2024年阿里云服务器租用费用&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核4G服务…

2016年认证杯SPSSPRO杯数学建模D题(第一阶段)NBA是否有必要设立四分线解题全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 D题 NBA是否有必要设立四分线 原题再现 NBA 联盟从 1946 年成立到今天&#xff0c;一路上经历过无数次规则上的变迁。有顺应民意、皆大欢喜的&#xff0c;比如 1973 年在技术统计中增加了抢断和盖帽数据&#xff1b;有应运而生、力挽狂澜的&am…

Nacos介绍和Eureka的区别

Nacos&#xff08;全称为 Alibaba Cloud Nacos&#xff0c;或简称为 Nacos&#xff09;是一个开源的分布式服务发现和配置管理系统。它由阿里巴巴集团开发并开源&#xff0c;旨在帮助开发人员简化微服务架构下的服务注册、发现和配置管理。 1、Nacos 提供了以下主要功能&#…

WPF 立体Border

WPF 立体Border &#xff0c;用来划分各个功能区块 在资源文件中&#xff0c;添加如下样式代码&#xff1a; <Style x:Key"BaseBorder" TargetType"Border"><Setter Property"Background" Value"White" /><Setter Prop…

如何用java使用es

添加依赖 如何连接es客户端 RestHighLevelClient 代表是高级客户端 其中hostname&#xff1a;es的服务器地址&#xff0c;prot端口号 &#xff0c;scheme&#xff1a;http还是https 如果不在使用es可以进行关闭&#xff0c;可以防止浪费一些资源 java如何创建索引&#xff1…

养好蜘蛛池的方法有哪些?如何正确的养

目前国内大部分正规网络科技公司都没有自己的蜘蛛池&#xff0c;甚至不知道什么是蜘蛛池&#xff0c;更不知道它的作用。 蜘蛛池起源于灰色产业。 它的前身是基于泛站点群体中大量活跃的蜘蛛而诞生的。 为了达到快速收录、快速排名的效果&#xff0c;很多行业都会将网站域名地址…

hyper-v虚拟机使用宿主机usb设备

文章目录 一、修改宿主机组策略二、使用 一、修改宿主机组策略 在宿主电脑上&#xff0c;按 winr 组合键打开运行窗口&#xff0c;输入 gpedit.msc 打开组策略编辑器&#xff0c;依次点击计算机配置- 管理模板- Windows 组件- 远程桌面服务- 远程桌面会话客户端- RemoteFX USB…

5.域控服务器都要备份哪些资料?如何备份DNS服务器?如何备份DHCP服务器?如何备份组策略?如何备份服务器状态的备份?

&#xff08;2.1) NTD(域控数据库&#xff09;备份 &#xff08;2.2&#xff09;DNS备份 &#xff08;2.3&#xff09;DHCP备份 &#xff08;2.4&#xff09;组策略备份 &#xff08;2.5&#xff09;CA证书备份 &#xff08;2.6&#xff09;系统状态备份 &#xff08;2.1)…

如何使用ospf (enps) 简单实践ospf协议

1. OSPF的基本概念 OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09;是一种广泛应用于TCP/IP网络中的内部网关协议&#xff08;Interior Gateway Protocol, IGP&#xff09;&#xff0c;主要用于在同一自治系统&#xff08;Autonomous Sys…

js工具方法记录

校验数字是否有效的11位手机号 function isValidPhoneNum(value: string) {return /^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(value) }手机号中间4位掩码 function maskPhoneNum(phone: string, space false) {if (!phone) {return }const reg /(\d{3})\d{4}(\d{4})/return pho…

人像抠图HumanSeg——基于大规模电话会议视频数据集的连接感知人像分割

前言 人像抠图将图像中的人物与背景进行像素级别的区分的技术。通过人像分割&#xff0c;可以实现诸如背景虚化、弹幕穿人等各种有趣的功能&#xff0c;为视频通话和影音观看提供更加优质和丰富的体验。由于广泛部署到Web、手机和边缘设备&#xff0c;肖像分割在兼顾分割精度的…

真机笔记(2)项目分析

目录 1. 项目&#xff1a; 2. 网络工程师工作流程 3. 实验 设备命名 登录密码 使用SSH协议 1. 项目&#xff1a; 竞标方&#xff1a;集成商、厂商、代理商、服务商、监理检测公司 在一个网络项目中&#xff0c;不同的角色承担着不同的职责和任务。以下是集成商、厂商、代…

Github多账号切换

在开发阶段&#xff0c;如果同时拥有多个开源代码托管平台的账户&#xff0c;在代码的管理上非常麻烦。那么&#xff0c;如果同一台机器上需要配置多个账户&#xff0c;怎样才能确保不冲突&#xff0c;不同账户独立下载独立提交呢&#xff1f; 我们以两个github账号进行演示 …

ChatGPT智能聊天系统源码v2.7.6全开源Vue前后端+后端PHP

测试环境:Linux系统CentOS7.6、宝塔、PHP7.4、MySQL5.6,根目录public,伪静态thinkPHP,开启ssl证书 具有文章改写、广告营销文案、编程助手、办公达人、知心好友、家庭助手、出行助手、社交平台内容、视频脚本创作、AI绘画、思维导图等功能 ai通道:文心一言、MiniMax、智…

【Linux C | 多线程编程】线程的退出

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 本文未经允许…

序列的使用

目录 序列的创建 序列的使 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 在许多数据库之中都会存在有一种数据类型 — 自动增长列&#xff0c;它能够创建流水号。如果想在 Oracle 中实现这样的自动增长列&#xff0c;可…

Ubuntu安装GPU驱动

ubuntu-drivers autoinstall 中间提示nvidia 470 有戏啊 nvidia-smi

蓝桥杯第192题 等差数列 C++ Java Python

目录 题目 思路和解题方法 复杂度 空间 时间 c 代码 Java 版本&#xff08;仅供参考&#xff09; Python 版本&#xff08;仅供参考&#xff09; 题目 思路和解题方法 首先&#xff0c;输入n和数组a的值。对数组a进行排序。计算数组a中相邻元素之间的差的最大公约数&…