初识websocket
之前对websocket是一点都不了解(H5都那么久了,实在不该),由于工作中需要了解websocket相关知识,自己查阅资料、模拟环境、调试等一系列操作之后从网上看到适合小白的一段代码,Ctrl+C,Ctrl+V之后,在代码中加了自己的理解,代码中注释是自己的一些看法,理解如有误,路过的大神多指正,小白级别,勿喷哦。
在服务端使用了nodejs中ws模块,以便在本地开启websocket服务端
安装node环境,并
npm install ws –g ; npm install uuid –g ; npm install
新建server.js
//服务端使用nodejs中ws模块,在wss对象中如果不写host参数,默认host指向localhost(127.0.0.1),如果使用默认的host,服务端和客户端在使用localhost和127.0.0.1时尽量书写一致,不然可能会引起websocket连接过慢哦,小伙伴们可以自行测试一下。 var WebSocket = require('ws'); var WebSocketServer = WebSocket.Server, wss = new WebSocketServer({ port: 8181 }); var uuid = require('node-uuid'); //unique identifier 惟一标识符 -->> uid // uuid.v1();基于时间戳v1()生成uid,uuid.v4()随机生成uid,通常使用v1,v4还是有概率重复的 var clients = []; //wsSend实现服务端广播客户端 function wsSend(type, client_uuid, nickname, message) { for (var i = 0; i < clients.length; i++) {//服务端会广播消息给多个客户端 var clientSocket = clients[i].ws; if (clientSocket.readyState === WebSocket.OPEN) {//客户端websocket处于连接状态才会广播消息 clientSocket.send(JSON.stringify({ "type": type, "id": client_uuid, "nickname": nickname, "message": message })); } } } var clientIndex = 1; wss.on('connection', function(ws) {//客户端open时,会触发服务端connection,服务端的消息会广播给多个客户端 var client_uuid = uuid.v4(); var nickname = "AnonymousUser" + clientIndex; clientIndex += 1; //当服务一直开启的状态,如果刷新客户端页面,此时clientIndex会一直增加,此处可以优化,客户端刷新时nickname保持当前的状态 //有客户端连接时,记录当前客户端的信息 clients.push({ "id": client_uuid, "ws": ws, "nickname": nickname }); console.log('client [%s] connected', client_uuid); var connect_message = nickname + " has connected"; wsSend("notification", client_uuid, nickname, connect_message); //个人想法:功能1实现服务端定时发送消息 /* setInterval(function(){ wsSend("xixi",client_uuid,nickname,"xixi"); },1000); */ //个人想法:想法2消息单项发送 //可以在发送消息或者连接成功之后发送消息给某个客户端 //结合1 2 在服务端针对某个客户端单项发送消息,可增加触发某个条件取消定时器发送消息 //个人想法: 想法3 实现websocket断开连接重连 console.log('client [%s] connected', client_uuid); ws.on('message', function(message) { if (message.indexOf('/nick') === 0) {//判断是什么消息类型,含有/nick表示修改昵称,不过通过'/nick'判断不算严谨,在发送消息的input框中输入"/nick haha hahah hha",会提示昵称修改 var nickname_array = message.split(' '); console.log(nickname_array.length); if (nickname_array.length >= 2) { var old_nickname = nickname; nickname = nickname_array[1]; var nickname_message = "Client " + old_nickname + " changed to " + nickname; wsSend("nick_update", client_uuid, nickname, nickname_message); } } else { wsSend("message", client_uuid, nickname, message); } }); //客户端失去连接,广播消息给其他客户端是哪个客户端失去了连接 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 + " has disconnected"; } wsSend("notification", client_uuid, nickname, disconnect_message); clients.splice(i, 1);//在客户端列表中删除已经失效的客户端 } } }; ws.on('close', function () { closeSocket(); }); process.on('SIGINT', function () {//nodejs 捕获当前进程接收到的信号 console.log("Closing things"); closeSocket('Server has disconnected'); process.exit();//退出当前进程 }); });
新建client.html文件
<!Doctype html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>WebSocket Echo Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link href="../bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" /> <style type="text/css"> li h2{ font-size:20px; } </style> <script src="../js/jquery-1.12.3.min.js"></script> <script src="../bootstrap-3.3.5/js/bootstrap.min.js"></script> <script> //建立连接 var ws = new WebSocket("ws://localhost:8181"); var nickname = ""; ws.onopen = function (e) { console.log('Connection to server opened'); } //页面显示 function appendLog(type, nickname, message) { if (typeof message == "undefined") return; 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); } //收到消息处理 ws.onmessage = function (e) { var data = JSON.parse(e.data); nickname = data.nickname; appendLog(data.type, data.nickname, data.message); console.log("ID: [%s] = %s", data.id, data.message); } ws.onclose = function (e) { appendLog("Connection closed"); console.log("Connection closed"); } //发送消息 function sendMessage() { var messageField = document.getElementById('message'); if (ws.readyState === WebSocket.OPEN) { ws.send(messageField.value); } messageField.value = ''; messageField.focus(); } //修改名称 function changName() { var name = $("#name").val(); if (ws.readyState === WebSocket.OPEN) { ws.send("/nick " + name); } } function disconnect() { ws.close(); } </script> </head> <body > <div> <div> <ul id="messages"></ul> <hr/> <form role="form" id="chat_form" onsubmit="sendMessage(); return false;"> <div> <input type="text" id="message" name="message" placeholder="Type text to echo in here" value="" autofocus/> </div> <button type="button" id="send" class="btn btn-primary" onclick="sendMessage();"> Send Message </button> </form> <div><span>nikename:</span><input id="name" type="text" /> <button class="btn btn-sm btn-info" onclick="changName();">change</button></div> </div> </div> </body> </html>
最新评论
- 相关文章
A-Frame WebVR(网页虚拟现实)快速开发入门教程
WebVR和WebGL应用程序接口使得我们已经可以在浏览器上创建虚拟现实(VR)体验,但从工程化的角度而言,开发社区还需要更多方便强大的开发库来简化编程,Mozilla的
常见面试题JS语言中四种函数调用方式实例讲解
JS的语言世界中函数(function)是一等公民,函数的调用有多种方法。普通调用这个是最常见和直接的方式:function
前端开发框架技术选型:Angular2 VS React VS jQuery
Angular和React是主流的2个前端开发框架,但是严格来说两者并非对等的概念。Angular是一个基于MVC(或者MVVM)的框架,包含model(模型)/view(视图)/controll...
深入理解CSS3滤镜(filter)功能和实例详解
CSS3滤镜功能源自SVG滤镜规范,SVG滤镜最早用来给矢量图添加类似PS中像素图的一些特效。
把这个滤镜功能引入到普通HTML元素中可以带来很有趣的效果(模糊、...深入理解JS和CSS3动画性能问题和技术选择
本文对比了JS及其框架和CSS3的动画性能,并深入剖析了其内在原因。技术结论大致如下:1. jQuery出于设计原因,在动画性能上表现最差2. CSS3由于把动画逻辑推给了...
使用HTML5 FileReader和Canvas压缩用户上传的图片
手机用户拍的照片通常会有2M以上,这对服务器带宽产生较大压力。因此在某些应用下(对图片要求不那么高)我们可以在客户端来压缩图片,然后再提交给服务器。总体...
使用HTML5 Canvas实现的界面元素截屏功能
深度贴图(depth map)概念简介和生成流程
Depth map 深度图是一张2D图片,每个像素都记录了从视点(viewpoint)到遮挡物表面(遮挡物就是阴影生成物体)的距离,这些像素对应的顶点对于观察者而言是“可...
Three.js入门教程2 - 着色器(下)
这是WebGL着色器教程的后半部分,如果你没看过前一篇,阅读这一篇教程可能会使你感到困惑,建议你翻阅前面的教程。
如何基于Canvas来模拟真实雨景Part2:重力掉落和雨滴融合
HTML网页布局:静态、自适应、流式、响应式
静态布局(Static Layout)即传统Web设计,对于PC设计一个Layout,在屏幕宽高有调整时,使用横向和竖向的滚动条来查阅被遮掩部分;对于移动设备,单独设计一个布...
使用requestAnimationFrame和Canvas给按钮添加绕边动画
要给按钮添加酷炫的绕边动画,可以使用Canvas来实现。基本的思路是创建一个和按钮大小相同的Canvas元素,内置在按钮元素中。然后在Canvas上实现边线环绕的动画。...
如何使用纯CSS3实现一个3D泡沫
要实现一个逼真的泡沫,涉及到比较复杂的光学/物理学知识。我们这里先简化下问题,实现一个相对简单而足够实用的泡沫元素。我们可以把基础的泡沫元素应用在很多场景中,比如水景、泡咖啡、啤酒甚至火焰特效中。泡沫首先是一个圆形元素.bubble
如何使用CSS3/SCSS实现逼真的车窗雨滴效果
在天气预报类的Web移动应用中,常常需要实现屏幕的雨滴效果,表示阴雨天气。感觉上比较神奇,其实想通了,这个效果的实现只需要一点物理知识和CSS3的简单变换。实现一个小雨滴首先雨滴是一个个小的椭圆形元素:.raindrop
更多...