基于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 服务端控制台

csharp 复制代码
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 message
            string 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 session
            if (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 path
            string 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 server
            var server = new ChatServer(IPAddress.Any, port);
            server.AddStaticContent(www, "/chat");

            // Start the server
            Console.Write("服务端启动...");
            server.Start();
            Console.WriteLine("完成!");

            Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");

            // Perform text input
            for (;;)
            {
                string line = Console.ReadLine();//接受输入
                if (string.IsNullOrEmpty(line))
                    break;

                // Restart the server
                if (line == "!")
                {//重启标识!
                    Console.Write("Server restarting...");
                    server.Restart();
                    Console.WriteLine("Done!");
                }

                // Multicast admin message to all sessions
                line = "[管理员] " + line;   //前缀admin管理员消息
                server.MulticastText(line);//广播
            }

            // Stop the server
            Console.Write("服务端停止...");
            server.Stop();
            Console.WriteLine("完成!");
        }
    }
}

2.2 客户端html

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 = true
    document.myform.disconnectButton.disabled = false
	myname=document.myform.myname.value
  }
//关闭
  function onClose(evt)
  {
    writeToScreen("disconnected\n")
    document.myform.connectButton.disabled = false
    document.myform.disconnectButton.disabled = true
  }
//发消息
  function onMessage(evt)
  {
    writeToScreen("接收<<" + evt.data + '\n')
  }
//错误
  function onError(evt)
  {
    writeToScreen('error: ' + evt.data + '\n')

    websocket.close()//关闭websocket

    document.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 客户端控制台

csharp 复制代码
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 again
            if (!_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 address
            string address = "127.0.0.1";
            if (args.Length > 0)
                address = args[0];

            // WebSocket server port 服务端口一致 9999
            int 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 client
            var client = new ChatClient(address, port);

            // Connect the client
            Console.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 input
            for (;;)
            {
                string line = Console.ReadLine();//接受输入
                if (string.IsNullOrEmpty(line))
                    break;

                // Disconnect the client
                if (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 client
            Console.Write("Client disconnecting...");
            client.DisconnectAndStop();//断开
            Console.WriteLine("Done!");
        }
    }
}

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

相关推荐
BAGAE20 小时前
HTTPS 加密原理介绍
java·c++·websocket·http·均值算法·启发式算法·最小二乘法
咖啡教室2 天前
每日一个计算机小知识:Socket
后端·websocket
paishishaba2 天前
HTTP、HTTPS 和 WebSocket 协议和开发
websocket·http·https·实时聊天
小范同学_3 天前
Spring集成WebSocket
java·spring boot·websocket·spring·1024程序员节
YUELEI1185 天前
Springboot WebSocket
spring boot·后端·websocket
Greedy Alg8 天前
Socket编程学习记录
网络·websocket·学习
Cxiaomu8 天前
React Native 项目中 WebSocket 的完整实现方案
websocket·react native·react.js
Arva .8 天前
WebSocket实现网站点赞通知
网络·websocket·网络协议
火星数据-Tina9 天前
LOL实时数据推送技术揭秘:WebSocket在电竞中的应用
网络·websocket·网络协议
paopaokaka_luck9 天前
基于SpringBoot+Vue的社区诊所管理系统(AI问答、webSocket实时聊天、Echarts图形化分析)
vue.js·人工智能·spring boot·后端·websocket