IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 关于websocket做即时通信功能 -> 正文阅读

[网络协议]关于websocket做即时通信功能

本文以网页端实现即时通信,用抢麦器的业务场景来完成即时的效果,需要Fleck.dll和Newtonsoft.Json.dll支持,Fleck是即时通信的核心,Newtonsoft.Json是json格式数据交互解析时用到的,均已上传到我的资源中,也可以在其他地方下载
1.后端socket服务实现
以控制台的方式简单实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Fleck;
using Newtonsoft.Json;
using System.Threading;

namespace WebSocketTest
{
    class Program
    {
        //存放连接服务器的socket对象
        private static List<IWebSocketConnection> allSockets = new List<IWebSocketConnection>();
        //创建服务,设置服务地址以及端口
        private static WebSocketServer server = new WebSocketServer("ws://0.0.0.0:7181");
        //当前在麦序上的人
        private static List<string> currentMic = new List<string>();
        //倒计时
        private static int timeDown= 15;

        static void Main(string[] args)
        {
            FleckLog.Level = LogLevel.Debug;
            //倒计时线程
            Thread timeControl = new Thread(() => {
                while (true) {
                    //倒计时结束,系统自动下第一个人的麦序
                    if (timeDown == 0)
                    {
                        currentMic.RemoveAt(0);
                        timeDown = 15;
                        MsgClass mc = new MsgClass();
                        mc.op = "systemdownmic";
                        mc.id = "";
                        Console.WriteLine("server:" + JsonConvert.SerializeObject(mc));
                        allSockets.ToList().ForEach(s => s.Send(JsonConvert.SerializeObject(mc)));
                    }
                    //如果麦序上已经没有人,则停止倒计时
                    if (currentMic.Count == 0)
                    {
                        System.Threading.Thread.CurrentThread.Suspend();
                    }
                    System.Threading.Thread.Sleep(1000);
                    timeDown--;
                }
            });
            server.Start(socket =>{
                socket.OnOpen = () =>
                {
                    Console.WriteLine("Open!");
                    allSockets.Add(socket);
                    //对后进来的用户同步当前麦序和计时器状态
                    if (currentMic.Count > 0)
                    {
                        MsgClass mc = new MsgClass();
                        mc.op = "init";
                        mc.currMic = currentMic;
                        mc.id = timeDown.ToString();
                        Console.WriteLine("server:" + JsonConvert.SerializeObject(mc));
                        socket.Send(JsonConvert.SerializeObject(mc));
                    }
                };
                socket.OnClose = () =>
                {
                    Console.WriteLine("Close!");
                    allSockets.Remove(socket);
                };
                socket.OnMessage = message =>
                {
                    Console.WriteLine("client:"+message);
                    MsgClass messageObj =JsonConvert.DeserializeObject<MsgClass>(message);
                    if (messageObj.op == "upmic")
                    {
                        //首次上麦,开始倒计时
                        if (currentMic.Count == 0)
                        {
                            timeDown = 15;
                            if (timeControl.ThreadState == ThreadState.Suspended)
                            {
                                timeControl.Resume();
                            }
                            else
                            {
                                timeControl.Start();
                            }
                        }
                        //禁止重复上麦
                        if (currentMic.Contains(messageObj.id))
                        {
                            return;
                        }
                        currentMic.Add(messageObj.id);
                    }
                    else if (messageObj.op == "downmic")
                    {
                        bool isfisrt = false;
                        if (currentMic.IndexOf(messageObj.id) == 0)
                        {
                            isfisrt = true;
                        }
                        currentMic.Remove(messageObj.id);
                        //下麦后没人在麦序上了则停止计时,时间重置为15s
                        if (currentMic.Count == 0)
                        {
                            if (timeControl.ThreadState == ThreadState.Running)
                            {
                                timeDown = 15;
                                timeControl.Suspend();
                            }
                        }
                        else if (isfisrt && currentMic.Count > 0)
                        {
                            //选手在第一个位置下麦后,且还有人在麦序,则重新计时
                            timeControl.Suspend();
                            timeDown = 15;
                            timeControl.Resume();
                        }
                    }
                    else if (messageObj.op == "alldownmic")
                    {
                        currentMic.Clear();
                        //全体下麦,清空倒计时,挂起倒计时线程
                        timeDown = 15;
                        timeControl.Suspend();
                    }
                    else if (messageObj.op == "addtime")
                    {
                        //麦序加时
                        timeDown += 15;
                    }
                    else if (messageObj.op == "controlmic")
                    {
                        //控麦下麦
                        if (messageObj.id == "")
                        {
                            return;
                        }
                        //若下的是第一个麦序,且后面没有人了,则停止计时器,重置计时
                        if (currentMic[0] == messageObj.id && currentMic.Count == 1)
                        {
                            timeControl.Suspend();
                            timeDown = 15;
                        }
                        else if (currentMic[0] == messageObj.id && currentMic.Count > 1)
                        {
                            //若下的是第一个麦序,且后面还有人,则重置计时,计时器继续
                            timeControl.Suspend();
                            timeDown = 15;
                            timeControl.Resume();
                        }
                        currentMic.Remove(messageObj.id);
                    }
                    else if (messageObj.op == "pause")
                    {
                        //暂停麦序
                        timeControl.Suspend();
                        //返回当前的倒计时
                        messageObj.id = timeDown.ToString();
                        allSockets.ToList().ForEach(s => s.Send(JsonConvert.SerializeObject(messageObj)));
                        return;
                    }
                    else if (messageObj.op == "start")
                    {
                        //开始麦序
                        timeControl.Resume();
                        //返回当前的倒计时
                        messageObj.id = timeDown.ToString();
                        allSockets.ToList().ForEach(s => s.Send(JsonConvert.SerializeObject(messageObj)));
                        return;
                    }
                    allSockets.ToList().ForEach(s => s.Send(message));
                };
            });


            var input = Console.ReadLine();
            while (input != "exit")
            {
                foreach (var socket in allSockets.ToList())
                {
                    socket.Send(input);
                }
                input = Console.ReadLine();
            }
        }
        
    }

    internal class MsgClass
    {
        public string op;
        public string id;
        public List<string> currMic = new List<string>();
    }
}

运行该程序
在这里插入图片描述

2.前端实现

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>抢麦器</title>
    <style type="text/css">
        body {
            margin:0px auto;
        }

        #main {
            width:500px;
            margin:20px auto;
        }

        #content {
            width:250px;
            height:300px;
            border:1px solid black;
        }
        #content div {
            background-color:RGB(248,248,248);
            color:black;
        }
        #content div.select {
            background-color:blue;
            color:white;
        }
    </style>
</head>
<body>
    <div id="main">
        <form id="sendForm">
            您的名字:<input id="myname" value="用户" onchange="powerControl()"/>
            <br /><br />
            <a id="upmic" href="javascript:void(0);" onclick="upMic();">上麦</a>&nbsp;&nbsp;
            <a id="downmic" href="javascript:void(0);" onclick="downMic();">下麦</a>&nbsp;&nbsp;        
            <a id="alldownmic" href="javascript:void(0);" onclick="allDownMic();" style="display:none;">全部下麦</a>&nbsp;&nbsp;      
            <a id="controlmic" href="javascript:void(0);" onclick="controlMic();" style="display:none;">控麦</a>&nbsp;&nbsp;       
            <a id="pauseAndStart" href="javascript:void(0);" onclick="pauseAndStart();" style="display:none;">暂停</a>&nbsp;&nbsp;  
            <a id="addtime" href="javascript:void(0);" onclick="addTime();" style="display:none;">加时</a>&nbsp;&nbsp;         
             剩余时间:<span id="time">0</span>
            <br />
            <div id="content">

            </div>
        </form>
        <pre id="incomming"></pre>
    </div>
    
    <script src="js/common/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        var timeout;//计时器

        function powerControl() {
            if ($("#myname").val() == "郭孛") {
                $("#alldownmic").show();
                $("#controlmic").show();
                $("#addtime").show();
                $("#pauseAndStart").show();
            }
        }
        function pauseAndStart() {
            //主持人控制暂停麦序或开始麦序
            if ($("#myname").val() != "郭孛") {
                return;
            }
            //没人在麦序上不允许操作开始或暂停
            if ($("#content div").length == 0) {
                return;
            }
            var json = {};
            if ($("#pauseAndStart").text()=="暂停"){
                json.op = "pause";
                $("#pauseAndStart").text("开始");
            }
            else {
                json.op = "start";
                $("#pauseAndStart").text("暂停");
            }
            ws.send(JSON.stringify(json));
        }
        function controlMic() {
            //主持人控制下麦
            if ($("#myname").val() != "郭孛") {
                return;
            }
            if ($("#content div.select").length == 0) {
                alert("请选中用户后操作!");
            }
            var json = {};
            json.op = "controlmic";
            json.id = $("#content div.select").attr("id");
            ws.send(JSON.stringify(json));
        }
        function upMic()
        {
            //禁止重复上麦
            if ($("#" + $("#myname").val()).length > 0) {
                return;
            }
            var json = {};
            json.op = "upmic";
            json.id = $("#myname").val();
            ws.send(JSON.stringify(json));
        }
        function downMic() {
            var json = {};
            json.op = "downmic";
            json.id = $("#myname").val();
            ws.send(JSON.stringify(json));
        }
        function allDownMic() {
            //仅指定人员可操作全体下麦
            if ($("#myname").val()!="郭孛") {
                return;
            }
            var json = {};
            json.op = "alldownmic";
            json.id = $("#myname").val();
            ws.send(JSON.stringify(json));
        }
        function addTime() {
            //仅指定人员可操作加时
            if ($("#myname").val() != "郭孛") {
                return;
            }
            //加时操作,麦上没人不给加
            if ($("#content div").length == 0) {
                return;
            }
            var json = {};
            json.op = "addtime";
            json.id = "";
            ws.send(JSON.stringify(json));
        }
        var start = function () {
            var inc = document.getElementById('incomming');
            var wsImpl = window.WebSocket || window.MozWebSocket;
            var form = document.getElementById('sendForm');
            var input = document.getElementById('sendText');
            $("#myname").val(new Date().valueOf());

            inc.innerHTML += "正在连接服务器......<br/>";

            // create a new websocket and connect
            window.ws = new wsImpl('ws://localhost:7181/');

            // when data is comming from the server, this method is called
            ws.onmessage = function (evt) {
                var data = JSON.parse(evt.data);
                if (data.op == "init") {
                    //对于后进来的用户应当同步正在进行的数据,如当前麦序上的人以及计时
                    //填充当前正在麦序上的人
                    data.currMic.forEach(c=> {
                        $("#content").append("<div id='" + c + "'>" + c + "</div>")
                    })
                    //初始化计时器
                    $("#time").text(data.id);
                    timeout = setInterval(function () {
                        var time = +$("#time").text();
                        $("#time").text(--time);
                        if (time <= 0) {
                            clearInterval(timeout);
                            //由服务端发起系统下麦
                            /*
                            var json = {};
                            json.op = "systemdownmic";
                            json.id = "";
                            ws.send(JSON.stringify(json));
                            */
                        }
                    }, 1000)
                }
                if (data.op == "upmic") {
                    //首次上麦,开始倒计时
                    if ($("#content div").length == 0) {
                        $("#time").text(15);
                        timeout = setInterval(function () {
                            var time = +$("#time").text();
                            $("#time").text(--time);
                            if (time <= 0) {
                                clearInterval(timeout);
                                //由服务端发起系统下麦
                                /*
                                var json = {};
                                json.op = "systemdownmic";
                                json.id = "";
                                ws.send(JSON.stringify(json));
                                */
                            }
                        },1000)
                    }
                    //上麦操作
                    if ($("#" + data.id + "").length == 0) {
                        $("#content").append("<div id='" + data.id + "'>" + data.id + "</div>");
                    }
                }
                else if (data.op == "downmic")
                {
                    var isfirst = false;
                    console.log($("#content div:first").attr("id") == data.id);
                    if ($("#content div:first").attr("id") == data.id) {
                        isfirst = true;
                    }
                    //下麦操作
                    $("#" + data.id).remove();
                    //只有第一个人下麦,且麦序上还有人时,则重新倒计时
                    if (isfirst && $("#content div").length > 0) {
                        $("#time").text(15);
                    }
                    else if ($("#content div").length == 0) {
                        //若麦序上没人了,则停止计时器
                        $("#time").text("");
                        clearInterval(timeout);
                    }
                }
                else if (data.op == "alldownmic") {
                    //全体下麦
                    $("#content").empty();
                    //清空倒计时
                    $("#time").empty();
                    clearInterval(timeout);
                }
                else if (data.op == "systemdownmic") {
                    //倒计时结束,系统自动下麦,默认下掉排在第一个人的麦序
                    $("#content div:first").remove();
                    clearInterval(timeout);
                    $("#pauseAndStart").text("暂停");
                    //若麦序上还有人,则重新倒计时
                    if ($("#content div").length > 0) {
                        $("#time").text(15);
                        timeout = setInterval(function () {
                            var time = +$("#time").text();
                            $("#time").text(--time);
                            if (time <= 0) {
                                clearInterval(timeout);
                                //由服务端发起系统下麦
                                /*
                                var json = {};
                                json.op = "systemdownmic";
                                json.id = "";
                                ws.send(JSON.stringify(json));
                                */
                            }
                        }, 1000)
                    }
                    else {
                        clearInterval(timeout);
                        $("#time").text("");
                    }
                }
                else if (data.op == "addtime") {
                    //加时操作,麦上没人不给加
                    if ($("#content div").length == 0) {
                        return;
                    }
                    var time = +$("#time").text();
                    $("#time").text(time + 15);
                }
                else if (data.op == "controlmic") {
                    //控麦操作,指定麦上的人员下麦,如果是指定的第一个,且麦上还有人则还需要重新计时
                    var selectMic = $("#content div[id='" + data.id + "']");
                    if (selectMic.length == 0) {
                        return;
                    }
                    if (selectMic.attr("id") == $("#content div:first").attr("id") && $("#content div").length > 1) {
                        $("#time").text(15);
                    }
                    else if (selectMic.attr("id") == $("#content div:first").attr("id") && $("#content div").length == 1) {
                        $("#time").text(0);
                        clearInterval(timeout);
                    }
                    selectMic.remove();
                }
                else if (data.op == "pause") {
                    //暂停麦序
                    clearInterval(timeout);
                    //补正倒计时
                    $("#time").text(data.id);
                }
                else if (data.op == "start") {
                    clearInterval(timeout);
                    //补正倒计时
                    $("#time").text(data.id);
                    //开始麦序
                    timeout = setInterval(function () {
                        var time = +$("#time").text();
                        $("#time").text(--time);
                        if (time <= 0) {
                            clearInterval(timeout);
                        }
                    }, 1000);
                }
                //inc.innerHTML += data.id + '<br/>';
            };

            // when the connection is established, this method is called
            ws.onopen = function () {
                inc.innerHTML += '连接成功<br/>';
            };

            // when the connection is closed, this method is called
            ws.onclose = function () {
                inc.innerHTML += '服务器连接已断开<br/>';
            }

            form.addEventListener('submit', function (e) {
                e.preventDefault();
                var val = input.value;
                ws.send(val);
                input.value = "";
            });

            $(document).on("click","#content div", function () {
                $("#content div").removeClass("select");
                $(this).addClass("select");
            })
        }
        window.onload = start;
    </script>
</body>
</html>

前端页面展示
在这里插入图片描述
可以看到前端页面打开连接成功后,控制台会同时打印相关信息,表示该页面已成功连接服务器,我们可以多开几个页面后执行相关的功能

在这里插入图片描述

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:27:49  更:2022-09-24 21:28:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:48:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码