WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室
from:https://blog.csdn.net/u010136741/article/details/51612594
【总目录】
【实例简介】
【效果图】
【客户端】
- <!DOCTYPE html>
- <html lang="cn">
- <head>
- <title>WebSocket chart application</title>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.css">
- <link rel="stylesheet" href="http://cdn.bootcss.com/tether/1.3.2/css/tether.css"/>
- <script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.js" ></script>
- <script src="http://cdn.bootcss.com/tether/1.3.2/js/tether.js"></script>
- <script src="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/js/bootstrap.js"></script>
- <script>
- var ws= new WebSocket('ws://www.liumumu.top:8180');
- var nickname;
- ws.onopen = function(e){
- console.log('Connection to server opened');
- }
- function appendLog(type,nickname, message,clientcount) {
- var messages = document.getElementById('messages');
- var messageElem = document.createElement("li");
- var preface_label;
- if(type==='notification') {
- preface_label = "<span class=\"label label-info\">*</span>";
- } else if(type==='nick_update') {
- preface_label = "<span class=\"label label-warning\">*</span>";
- } else {
- preface_label = "<span class=\"label label-success\">" + nickname + "</span>";
- }
- var message_text = "<h2>" + preface_label + " " + message + "</h2>";
- messageElem.innerHTML = message_text;
- messages.appendChild(messageElem);
- var count_people = document.getElementById("count_people");
- count_people.innerHTML = clientcount;
- }
- ws.onmessage = function(e){
- var data = JSON.parse(e.data);
- nickname = data.nickname;
- appendLog(data.type,data.nickname, data.message,data.clientcount);
- console.log("ID: [%s] = %s", data.id, data.message);
- }
- function sendMessage(){
- var message = $('#message').val().trim();
- if(message.length<1){
- alert("不能发送空内容!");
- return;
- }
- ws.send($('#message').val());
- $('#message').val("");
- $('#message').focus();
- console.log(ws.bufferedAmount);
- }
- </script>
- </head>
- <body lang="cn">
- <div class="vertical-center">
- <div class="container">
- <h2>多人在线聊天DEMO</h2>
- <hr />
- <p>当前在线人数:<span id="count_people">0</span></p>
- <ul id="messages" class="list-unstyled">
- </ul>
- <hr />
- <form role="form" id="chat_form" onsubmit="sendMessage(); return false;">
- <div class="form-group">
- <input class="form-control" type="text" name="message" id="message"
- placeholder="输入聊天内容" value="" autofocus/>
- </div>
- <button type="button" id="send" class="btn btn-primary"
- onclick="sendMessage();">发送!</button>
- </form>
- </div>
- </div>
- </body>
- </html>
【服务器端】
- var WebSocket = require('ws');
- var WebSocketServer = WebSocket.Server,
- wss = new WebSocketServer({port: 8180});
- var uuid = require('node-uuid');
- var clients = [];
- function wsSend(type, client_uuid, nickname, message,clientcount) {
- for(var i=0; i<clients.length; i++) {
- var clientSocket = clients[i].ws;
- if(clientSocket.readyState === WebSocket.OPEN) {
- clientSocket.send(JSON.stringify({
- "type": type,
- "id": client_uuid,
- "nickname": nickname,
- "message": message,
- "clientcount":clientcount,
- }));
- }
- }
- }
- var clientIndex = 1;
- wss.on('connection', function(ws) {
- var client_uuid = uuid.v4();
- var nickname = "游客"+clientIndex;
- clientIndex+=1;
- clients.push({"id": client_uuid, "ws": ws, "nickname": nickname});
- console.log('client [%s] connected', client_uuid);
- var connect_message = nickname + " 来了";
- wsSend("notification", client_uuid, nickname, connect_message,clients.length);
- ws.on('message', function(message) {
- if(message.indexOf('/nick') === 0) {
- var nickname_array = message.split(' ');
- if(nickname_array.length >= 2) {
- var old_nickname = nickname;
- nickname = nickname_array[1];
- var nickname_message = "用户 " + old_nickname + " 改名为: " + nickname;
- wsSend("nick_update", client_uuid, nickname, nickname_message,clients.length);
- }
- } else {
- wsSend("message", client_uuid, nickname, message,clients.length);
- }
- });
- var closeSocket = function(customMessage) {
- for(var i=0; i<clients.length; i++) {
- if(clients[i].id == client_uuid) {
- var disconnect_message;
- if(customMessage) {
- disconnect_message = customMessage;
- } else {
- disconnect_message = nickname + " 走了";
- }
- clients.splice(i, 1);
- wsSend("notification", client_uuid, nickname, disconnect_message,clients.length);
- }
- }
- }
- ws.on('close', function() {
- closeSocket();
- });
- process.on('SIGINT', function() {
- console.log("Closing things");
- closeSocket('Server has disconnected');
- process.exit();
- });
- });
我们定义了wsSend函数用来处理消息的广播。对每个连接的用户,我们默认给他分配为游客。为了实现广播,我们用clients数组来保存连接的用户。
WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室的更多相关文章
- Spring WebSocket初探2 (Spring WebSocket入门教程)<转>
See more: Spring WebSocket reference整个例子属于WiseMenuFrameWork的一部分,可以将整个项目Clone下来,如果朋友们有需求,我可以整理一个独立的de ...
- PySide——Python图形化界面入门教程(五)
PySide——Python图形化界面入门教程(五) ——QListWidget 翻译自:http://pythoncentral.io/pyside-pyqt-tutorial-the-qlistw ...
- Elasticsearch入门教程(五):Elasticsearch查询(一)
原文:Elasticsearch入门教程(五):Elasticsearch查询(一) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
- RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)
原文:RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
- 无废话ExtJs 入门教程五[文本框:TextField]
无废话ExtJs 入门教程五[文本框:TextField] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个两个文本框.如下所示代码区的第42行位置,items: ...
- 转:Scrapy安装、爬虫入门教程、爬虫实例(豆瓣电影爬虫)
Scrapy在window上的安装教程见下面的链接:Scrapy安装教程 上述安装教程已实践,可行.(本来打算在ubuntu上安装Scrapy的,但是Ubuntu 磁盘空间太少了,还没扩展磁盘空间,所 ...
- Scrapy安装、爬虫入门教程、爬虫实例(豆瓣电影爬虫)
Scrapy在window上的安装教程见下面的链接:Scrapy安装教程 上述安装教程已实践,可行.(本来打算在ubuntu上安装Scrapy的,但是Ubuntu 磁盘空间太少了,还没扩展磁盘空间,所 ...
- vue教程2-04 vue实例简单方法
vue教程2-04 vue实例简单方法 vue实例简单方法: vm.$el -> 就是元素 vm.$data -> 就是data <!DOCTYPE html> <htm ...
- 使用Servlet和JSP实现一个简单的Web聊天室系统
1 问题描述 利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...
随机推荐
- js 数组分解 解构
// ES5 a = list[0], rest = list.slice(1) // ES6 [a, ...rest] = list
- NET:Checkboxlist,Dropdownlist 加入ToolTip说明
ToolTip属性: ToolTip 类 (System.Windows.Controls) 表示创建弹出项的控件.该弹出项可显示界面中元素的相关信息.命名空间: System.Windows.Co ...
- 关于vector push_back()与其他方式读取数据的效率对比(转)
引言: 在读取大量数据(数组)时,使用vector会尽量保证不会炸空间(MLE),但是相比于scanf的读取方式会慢上不少.但到底效率相差有多大,我们将通过对比测试得到结果. 测试数据:利用srand ...
- 搭建 SMTP mail
邮件协议需要配置client 端 和 server 端,在linux redhat 下 client 端: 使用linux 自带的Evolution,2.12.3, 主要配置在preferrence ...
- 【FinancialKnowledge】拨备
一句话: 银行拨备就是银行贷款损失减值准备的俗称,其相当于为承担风险和损失的金融资产计提的准备金 通俗易懂的解释见:https://wallstreetcn.com/articles/3307725
- 如何为Drupal缓存对象指定缓存类?
什么意思?意思是说,假如你有这样的需求,需要将cache_page缓存到数据库,其它的都缓存到memcache,这该怎么办? 看看_cache_get_object()的实现你就会知道上面的问题该怎么 ...
- 基于RxJava2+Retrofit2简单易用的网络请求实现
代码地址如下:http://www.demodashi.com/demo/13473.html 简介 基于RxJava2+Retrofit2实现简单易用的网络请求,结合android平台特性的网络封装 ...
- 【Shiro】Apache Shiro架构之权限认证(Authorization)
Shiro系列文章: [Shiro]Apache Shiro架构之身份认证(Authentication) [Shiro]Apache Shiro架构之集成web [Shiro]Apache Shir ...
- const和readonly关键字
不知道大家对const和readonly这两个关键字的区别有什么了解,原来自己之前还真不清楚它们到底是怎么回事,那么如果你也不是很清楚的话,可以一起来探讨一下.在了解这两个关键字的时候我们先来了解一下 ...
- Microsoft Team Foundation Server 2010 安装 序列号 注册码(转载)
安装过程: 一.安装操作系统 安装Windows 2008 R2简体中文版 二.准备安装过程中的需要的用户账户,并设置相应权限. 具体流程如下: 1.点击“开始”——“管理工具”——“计算机管理” 2 ...