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

【总目录】

 
 

【实例简介】

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

【效果图】

 
 
 

【客户端】

 
    web页面主要呈现在线人数,聊天信息,一个输入框和发送按钮,上代码:
 
  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. ws.onmessage = function(e){
  36. var data = JSON.parse(e.data);
  37. nickname = data.nickname;
  38. appendLog(data.type,data.nickname, data.message,data.clientcount);
  39. console.log("ID: [%s] = %s", data.id, data.message);
  40. }
  41. function sendMessage(){
  42. var message = $('#message').val().trim();
  43. if(message.length<1){
  44. alert("不能发送空内容!");
  45. return;
  46. }
  47. ws.send($('#message').val());
  48. $('#message').val("");
  49. $('#message').focus();
  50. console.log(ws.bufferedAmount);
  51. }
  52. </script>
  53. </head>
  54. <body lang="cn">
  55. <div class="vertical-center">
  56. <div class="container">
  57. <h2>多人在线聊天DEMO</h2>
  58. <hr />
  59. <p>当前在线人数:<span id="count_people">0</span></p>
  60. <ul id="messages" class="list-unstyled">
  61. </ul>
  62. <hr />
  63. <form role="form" id="chat_form" onsubmit="sendMessage(); return false;">
  64. <div class="form-group">
  65. <input class="form-control" type="text" name="message" id="message"
  66. placeholder="输入聊天内容" value="" autofocus/>
  67. </div>
  68. <button type="button" id="send" class="btn btn-primary"
  69. onclick="sendMessage();">发送!</button>
  70. </form>
  71. </div>
  72. </div>
  73. </body>
  74. </html>
    javascript 部分,连接websocket成功之后,主要是监听数据返回,和发送数据。
    当用户编辑好内容,点击发送按钮是调用sendMessage方法,发送数据,如果需要修改昵称,则发送数据格式为"/nick 昵称"。
   当服务器返回数据到客户端,我们通过appendLog方法对数据做处理,根据type字段,判断是显示用户离线在线信息,还是显示聊天信息。最后更新在线人数。
 

【服务器端】

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

我们定义了wsSend函数用来处理消息的广播。对每个连接的用户,我们默认给他分配为游客。为了实现广播,我们用clients数组来保存连接的用户。

WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室的更多相关文章

  1. Spring WebSocket初探2 (Spring WebSocket入门教程)<转>

    See more: Spring WebSocket reference整个例子属于WiseMenuFrameWork的一部分,可以将整个项目Clone下来,如果朋友们有需求,我可以整理一个独立的de ...

  2. PySide——Python图形化界面入门教程(五)

    PySide——Python图形化界面入门教程(五) ——QListWidget 翻译自:http://pythoncentral.io/pyside-pyqt-tutorial-the-qlistw ...

  3. Elasticsearch入门教程(五):Elasticsearch查询(一)

    原文:Elasticsearch入门教程(五):Elasticsearch查询(一) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...

  4. RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)

    原文:RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...

  5. 无废话ExtJs 入门教程五[文本框:TextField]

    无废话ExtJs 入门教程五[文本框:TextField] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个两个文本框.如下所示代码区的第42行位置,items: ...

  6. 转:Scrapy安装、爬虫入门教程、爬虫实例(豆瓣电影爬虫)

    Scrapy在window上的安装教程见下面的链接:Scrapy安装教程 上述安装教程已实践,可行.(本来打算在ubuntu上安装Scrapy的,但是Ubuntu 磁盘空间太少了,还没扩展磁盘空间,所 ...

  7. Scrapy安装、爬虫入门教程、爬虫实例(豆瓣电影爬虫)

    Scrapy在window上的安装教程见下面的链接:Scrapy安装教程 上述安装教程已实践,可行.(本来打算在ubuntu上安装Scrapy的,但是Ubuntu 磁盘空间太少了,还没扩展磁盘空间,所 ...

  8. vue教程2-04 vue实例简单方法

    vue教程2-04 vue实例简单方法 vue实例简单方法: vm.$el -> 就是元素 vm.$data -> 就是data <!DOCTYPE html> <htm ...

  9. 使用Servlet和JSP实现一个简单的Web聊天室系统

    1 问题描述                                                利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...

随机推荐

  1. SVN:This client is too old to work with working copy…解决方法

    昨天升级了一下苹果系统到10.10,扁平化确实不错,高兴之余多少有些不快.我的svn出现故障,总是提示我  SVN:This client is too old to work with workin ...

  2. One simple WPF & C# RayTracer

    What's this 这是一个软渲染光线追踪器,基于c#和wpf技术. How to use 这份代码的唯一参考书是Ray Tracing From The Ground Up,在学习和阅读本书过程 ...

  3. 42、Java国际化

    简介 国际化的英文单词是Internationalization,有时检测I18N,类似于I18N还有L10N,是Location本地化的简写. Java或计划主要通过如下三个类实现 1.java.u ...

  4. struts2 页面向Action传参方式

    1.基本属性注入 我们可以直接将表单数据项传递给Action,而Action只需要提供基本的属性来接收参数即可,这种传参方式称为基本属性注入.例如 jsp页面: <s:form method=& ...

  5. Drupal的钩子系统

    Drupal的很多功能都是可以定制的.以导航菜单为例,blog模块需要在菜单上添加一些功能,comment模块需要在菜单上添加一些功能,我们开发的自定义模块也需要在菜单上添加一些功能.Drupal开发 ...

  6. RxJava API使用示例

    概述 RxJava API示例代码,可离线查看rxjava1.0大部分API的marble图,描述,示例代码,并支持示例代码实时输出及展示执行结果. 详细 代码下载:http://www.demoda ...

  7. 什么是SQL注入式攻击?

    什么是SQL注入式攻击? 所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令.在某些表单中,用户输入的内容直接用来构造(或者影响 ...

  8. 常用 cdn

    http://www.bootcdn.cn/ jquery <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.j ...

  9. Aspose.Cells 导出指定格式项目(金额、数字、文本)

    Aspose.Cells为开发人员提供了许多内嵌的数字和日期格式,开发人员可以通过Style对象的Number属性调用这些内嵌格式,下面是Aspose.Cells提供的显示格式:Value Type ...

  10. pycharm 社区版

    这个是免费版.到3.1.13 http://pan.baidu.com/s/1bnvPdtt 没用过idea的商业版,不知道为什么它的更新那么蛋疼,不能增量更新,每次都得手动下载完整的压缩包.