• WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室


    from:https://blog.csdn.net/u010136741/article/details/51612594

    【总目录】

     
     

    【实例简介】

     
        本文,我们通过nodejs和javascript实现一个网页聊天室的demo。主要包括,聊天,改用户名,查看其他用户在线状态的功能。大致流程为,用户访问网页,即进入聊天状态,成为新游客,通过底部的输入框,可以输入自己想说的话,点击发布,信息呈现给所有在聊天的人的页面。用户可以实时修改自己的昵称,用户离线上线都会实时广播给其他用户!
     

    【效果图】

     
     
     

    【客户端】

     
        web页面主要呈现在线人数,聊天信息,一个输入框和发送按钮,上代码:
     
    [html] view plain copy
     
    1. <!DOCTYPE html>  
    2. <html lang="cn">  
    3. <head>  
    4.     <title>WebSocket chart application</title>  
    5.     <meta charset="utf-8">  
    6.     <meta name="viewport" content="width=device-width, initial-scale=1">  
    7.     <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.css">  
    8.     <link rel="stylesheet" href="http://cdn.bootcss.com/tether/1.3.2/css/tether.css"/>  
    9.     <script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.js" ></script>  
    10.     <script src="http://cdn.bootcss.com/tether/1.3.2/js/tether.js"></script>  
    11.     <script src="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/js/bootstrap.js"></script>  
    12.     <script>  
    13.         var ws= new WebSocket('ws://www.liumumu.top:8180');  
    14.         var nickname;  
    15.         ws.onopen = function(e){  
    16.             console.log('Connection to server opened');  
    17.         }  
    18.         function appendLog(type,nickname, message,clientcount) {  
    19.                 var messages = document.getElementById('messages');  
    20.                 var messageElem = document.createElement("li");  
    21.                 var preface_label;  
    22.             if(type==='notification') {  
    23.                         preface_label = "<span class="label label-info">*</span>";  
    24.                     } else if(type==='nick_update') {  
    25.                         preface_label = "<span class="label label-warning">*</span>";  
    26.                     } else {  
    27.                         preface_label = "<span class="label label-success">" + nickname + "</span>";  
    28.                     }  
    29.                 var message_text = "<h2>" + preface_label + "  " + message + "</h2>";  
    30.                 messageElem.innerHTML = message_text;  
    31.                 messages.appendChild(messageElem);  
    32.             var count_people = document.getElementById("count_people");  
    33.                         count_people.innerHTML = clientcount;  
    34.   
    35.             }  
    36.         ws.onmessage = function(e){  
    37.             var data = JSON.parse(e.data);  
    38.             nickname = data.nickname;  
    39.                 appendLog(data.type,data.nickname, data.message,data.clientcount);  
    40.                 console.log("ID: [%s] = %s", data.id, data.message);  
    41.   
    42.   
    43.         }  
    44.         function sendMessage(){  
    45.             var message = $('#message').val().trim();  
    46.             if(message.length<1){  
    47.                 alert("不能发送空内容!");  
    48.                 return;  
    49.             }  
    50.             ws.send($('#message').val());  
    51.             $('#message').val("");  
    52.             $('#message').focus();  
    53.             console.log(ws.bufferedAmount);  
    54.         }  
    55.     </script>  
    56. </head>  
    57. <body lang="cn">  
    58.     <div class="vertical-center">  
    59.     <div class="container">  
    60.         <h2>多人在线聊天DEMO</h2>  
    61.     <hr />  
    62.     <p>当前在线人数:<span id="count_people">0</span></p>  
    63.     <ul id="messages" class="list-unstyled">  
    64.   
    65.         </ul>  
    66.         <hr />  
    67.     <form role="form" id="chat_form" onsubmit="sendMessage(); return false;">  
    68.             <div class="form-group">  
    69.                 <input class="form-control" type="text" name="message" id="message"  
    70.                     placeholder="输入聊天内容" value="" autofocus/>  
    71.             </div>  
    72.             <button type="button" id="send" class="btn btn-primary"  
    73.           onclick="sendMessage();">发送!</button>  
    74.     </form>  
    75.     </div>  
    76.     </div>  
    77. </body>  
    78. </html>  
        
        javascript 部分,连接websocket成功之后,主要是监听数据返回,和发送数据。
        当用户编辑好内容,点击发送按钮是调用sendMessage方法,发送数据,如果需要修改昵称,则发送数据格式为"/nick 昵称"。
       当服务器返回数据到客户端,我们通过appendLog方法对数据做处理,根据type字段,判断是显示用户离线在线信息,还是显示聊天信息。最后更新在线人数。
     

    【服务器端】

     
        服务器端主要是接收信息,判断是聊天信息还是重命名信息,然后发送广播。同时,当用户连接上服务器端或者关闭连接时,服务器也会发送广播通知其他用户。
    [javascript] view plain copy
     
    1. var WebSocket = require('ws');  
    2. var WebSocketServer = WebSocket.Server,  
    3.     wss = new WebSocketServer({port: 8180});  
    4. var uuid = require('node-uuid');  
    5.   
    6. var clients = [];  
    7.   
    8. function wsSend(type, client_uuid, nickname, message,clientcount) {  
    9.   for(var i=0; i<clients.length; i++) {  
    10.     var clientSocket = clients[i].ws;  
    11.     if(clientSocket.readyState === WebSocket.OPEN) {  
    12.       clientSocket.send(JSON.stringify({  
    13.         "type": type,  
    14.         "id": client_uuid,  
    15.         "nickname": nickname,  
    16.         "message": message,  
    17.         "clientcount":clientcount,  
    18.       }));  
    19.     }  
    20.   }  
    21. }  
    22.   
    23. var clientIndex = 1;  
    24.   
    25. wss.on('connection', function(ws) {  
    26.   var client_uuid = uuid.v4();  
    27.   var nickname = "游客"+clientIndex;  
    28.   clientIndex+=1;  
    29.   clients.push({"id": client_uuid, "ws": ws, "nickname": nickname});  
    30.   console.log('client [%s] connected', client_uuid);  
    31.   
    32.   var connect_message = nickname + " 来了";  
    33.   wsSend("notification", client_uuid, nickname, connect_message,clients.length);  
    34.   
    35.   ws.on('message', function(message) {  
    36.     if(message.indexOf('/nick') === 0) {  
    37.       var nickname_array = message.split(' ');  
    38.       if(nickname_array.length >= 2) {  
    39.         var old_nickname = nickname;  
    40.         nickname = nickname_array[1];  
    41.         var nickname_message = "用户 " + old_nickname + " 改名为: " + nickname;  
    42.         wsSend("nick_update", client_uuid, nickname, nickname_message,clients.length);  
    43.       }  
    44.     } else {  
    45.       wsSend("message", client_uuid, nickname, message,clients.length);  
    46.     }  
    47.   });  
    48.   
    49.   var closeSocket = function(customMessage) {  
    50.     for(var i=0; i<clients.length; i++) {  
    51.         if(clients[i].id == client_uuid) {  
    52.             var disconnect_message;  
    53.             if(customMessage) {  
    54.                 disconnect_message = customMessage;  
    55.             } else {  
    56.                 disconnect_message = nickname + " 走了";  
    57.             }  
    58.   
    59.           clients.splice(i, 1);  
    60.           wsSend("notification", client_uuid, nickname, disconnect_message,clients.length);  
    61.         }  
    62.     }  
    63.   }  
    64.   ws.on('close', function() {  
    65.       closeSocket();  
    66.   });  
    67.   
    68.   process.on('SIGINT', function() {  
    69.       console.log("Closing things");  
    70.       closeSocket('Server has disconnected');  
    71.       process.exit();  
    72.   });  
    73. });  

        我们定义了wsSend函数用来处理消息的广播。对每个连接的用户,我们默认给他分配为游客。为了实现广播,我们用clients数组来保存连接的用户。
  • 相关阅读:
    BOM
    定位
    浮动
    行内元素和块级元素
    Java SE之正则表达式五:切割
    Java SE之正则表达式四:获取
    Java SE之正则表达式三:替换
    Java SE之正则表达式二:匹配
    Java SE之正则表达式一:概述
    [C++]PAT乙级1012.数字分类 (20/20)
  • 原文地址:https://www.cnblogs.com/liuqiyun/p/8668576.html
Copyright © 2020-2023  润新知