初识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>
最新评论
- 相关文章
微信公众号在线生成二维码带参数怎么搞?
带参数二维码是微信公众号渠道二维码的一种实现
微信的带参数二维码有两种,一种是临时二维码,一种是永久二维码,但是永久二维码的生成是有个数限制的,微...踏得网精选2016年度10大最佳HTML5动画
踏得网精选2016年度最酷最新的HTML5动画集,评选标准为:创意新颖度+实现技术难度+趣味程度。使用一些在线H5生成工具的作品,因其主要使用图片和CSS3套路动画,...
创建非矩形网页页面元素的常用技术和实例代码
非矩形设计正在变成一种时尚,比如波浪形、菱形、三角形等:而随着技术发展,这种设计在技术实现上也变得更容易。本文以最简单的三角形为例,演示使用5种方法来...
CSS3特性查询(Feature Query: @supports)功能简介
这是2017年不能不了解和学习的一个CSS新特性,非常实用,考虑到现实世界浏览器的复杂性,该特性本应该先于其他新特性出来。我们已经知道使用媒体查询(Media Que...
HTTP/2背景和新特性简介
计算WebGL中的uniforms变量使用数
在使用Three.js为人体模型加载皮肤材料时,启用了skinning:true的参数。有时候会导致GL编译错误,提示“too many uniforms”。下面的文章有助于理解错误原因和检...
Blender2.7 快捷键一览表
通用操作
停止当前操作:ESC
快捷搜索:SPACE撤销:ctrl+z重做:ctrl+shift+z渲染:F12
单选:鼠标右键(RMB)全选:A
框选:B
刷选:...Three.js入门教程6 - 创建全景图和纹理
全景图非常酷。使用Three.js做一个属于自己的全景图并不是那么困难。要做一个全景图,你需要一个软件用来做一张全景图片。我使用了iPhone上的Microsoft Photosyn...
Three.js入门教程2 - 着色器(上)
Three.js入门教程1 - 基础知识和创建一个红色球体
[ TECHBROOD注:Three.js是一个主流的开源WebGL库,WebGL允许使用JavaScript直接操作GPU,在网页上实现3D效果。
Google的工程师Paul在网站aerotwist.com上...WebGL入门教程2 - GPU基本概念和工作流水线(渲染管道)
WebGL入门教程1 - 3D绘图基础知识
现代浏览器努力使得Web用户体验更为丰富,而WebGL正处于这样的技术生态系统的中心位置。其应用范围覆盖在线游戏、大数据可视化、计算机辅助设计、虚拟现实以及数...
jQuery Ribbles - 基于WebGL的水面涟漪动效插件
使用jQuery
如何使用纯CSS3实现一个3D泡沫
要实现一个逼真的泡沫,涉及到比较复杂的光学/物理学知识。我们这里先简化下问题,实现一个相对简单而足够实用的泡沫元素。我们可以把基础的泡沫元素应用在很多场景中,比如水景、泡咖啡、啤酒甚至火焰特效中。泡沫首先是一个圆形元素.bubble
在PHP网页程序中执行Sass/Compass命令
我们需要在wow云开发平台支持sass/compass等预编译样式语言,为此我们首先尝试了scssphp扩展,但是在支持最新语法上,经常会出现异常。所以我们采用了代理的方式...
更多...