JavaScript WebSocket 使用总结
翻看之前写的 Highcharts使用总结 和 前后台交互之传参方式,想对 WebSocket 单独写一个使用总结。
一、认识 WebSocket 。
WebSocket 是 H5 新出的一种协议,为解决客户端与服务端实时通信而产生的技术。
通过 HTTP/HTTPS 协议进行三次握手后创建一个用于交换数据的 TCP连接,此后服务端与客户端通过此 TCP 连接进行实时通信,任意时刻都可以相互推送消息,也允许跨域通信。(三.2)
比较:Ajax 轮询方式,客户端隔一段时间询问服务器,看是否有数据,是客户端主动请求的。
XHR 受到域的限制。
Long Poll 长轮询原理跟 Ajax 差不多,都是轮询方式,不过采取的是阻塞模型,即客户端发起连接后,如果没消息,就一直不返回Response给客户端,直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。
二、简明入门。
1、创建一个新的 WebSocket 对象:
var Socket = new WebSocket(url,[protocal]);
参数解释: (1)url : 要连接的URL ; (2)[protocal] : 可选,指定一个服务器支持的协议。
2、WebSocket 属性:
(1) Socket.readyState —— readyState 代表 ReadOnly 属性的状态。
取值:0 —— 连接尚未建立;
1 —— 连接已经建立;
2 —— 连接正在关闭;
3 —— 连接已经关闭或不可用。
(2)Socket.bufferedAmount —— 读属性的 bufferedAmount 代表文本的字节数,utf-8 的排列使用 send() 方法。
3、WebSocket 事件:
事件 | 处理程序 | 说明 |
open | Socket.onopen | 发生在套接字建立连接 |
message | Socket.onmessage | 发生时客户端收到来自服务器的数据 |
error | Socket.onerror | 发生时有通信错误 |
close | Socket.onclose | 发生在连接关闭 |
4、WebSocket 方法:
(1)Socket.send() —— send(data) 方法用来连接传输数据;
(2)Socket.close() —— close()方法将被用于终止任何现有连接。
三、用法示例。
<a href="javascript:WebSocketTest()">点击运行WebSocket</a>
function WebSocketTest() { if ("WebSocket" in window) { alert("WebSocket is supported by your Browser!"); // 打开WebSocket var ws = new WebSocket("ws://127.0.0.1:2012"); ws.onopen = function() { // Web Socket is connected, send data using send() ws.send("121314"); alert("Message is sending"); }; ws.onmessage = function (evt) { var received_msg = evt.data; alert("Message is received"); }; ws.onclose = function() { // websocket is closed alert("Connection is closed"); }; } else { // The browser doesn't support WebSocket alert("WebSocket NOT supported by your Browser!!!"); } }
四、项目实例。
项目用于物流仓库,管理仓库货架货位、货位灯、出库入库统计以及仓库实时温湿度统计显示。采用 WebSocket 和服务器连接,获取接口数据比较方便。
页面有显示“服务器状态”的红绿色圆形:
<div class="pull-right"> <span>服务器状态:</span> <span id="wsServerStatus">未连接</span> <div id="sx" style="width:12px;height:12px;border-radius:6px;background-color:red;" class="inline"></div> </div>
红色代表“未连接”,绿色代表“连接”。
页面加载时建立连接:
<script> var ws; var SocketCreated = false; window.onload = function Connect() { if (SocketCreated || (ws.readyState == 0 || ws.readyState == 1)) { // readyState属性表示ReadOnly属性的状态。等于0或者1表示连接未建立 SocketCreated = false; ws.close(); document.getElementById("wsServerStatus").innerHTML = "连接未建立"; document.getElementById("sx").style.background = "red"; } else { document.getElementById("wsServerStatus").innerHTML = "准备连接到服务器 ..."; if ("WebSocket" in window) { ws = new WebSocket("ws://192.168.1.108:2012"); }else if("MozWebSocket" in window) { ws = new MozWebSocket("ws://192.168.1.108:2012"); } SocketCreated = true; ws.onopen = WSonOpen; ws.onmessage = WSonMessage; ws.onclose = WSonClose; ws.onerror = WSonError; } }; function WSonOpen() { document.getElementById("wsServerStatus").innerHTML = "连接已建立"; document.getElementById("sx").style.background = "green"; }; function WSonMessage(event) { var msg = JSON.parse(event.data); switch (msg.key) { case "/device/data": case "/device/status": var n = document.getElementById("content-main").childElementCount; for (var i = 1; i < n; i++) { try{ var m = document.getElementById("content-main").children[i]; m.contentWindow.ParseValue(msg.body); }catch(err){ alert("error:" + err); } } break; } }; function WSonClose() { document.getElementById("wsServerStatus").innerHTML = "连接已关闭"; document.getElementById("sx").style.background = "red"; }; function WSonError() { document.getElementById("wsServerStatus").innerHTML = "远程连接中断"; document.getElementById("sx").style.background = "red"; }; function WsSend(val) { ws.send(val); } </script>
五、WebSocket 小应用——聊天室
因为这是去年做的一个小东西,当时的公司后台帮我写了个聊天服务器,所以可以正常使用这个聊天室,挺好玩的,可以相互发送消息,但是现在我这里只有前端的(⊙o⊙)…
<div class="talk_div"> <div id="skm_LockPane" class="LockOff"></div> <header id="form1" runat="server"> <h2>聊天室</h2> <h4>点击连接按钮,会通过WebSocket发起连接,进行会话</h4> </header> <div class="talk_container"> <form> 服务器地址:<input type="text" id="Connection"><br> 用 户 名:<input type="name" id="txtName"> <button id="ToggleConnection" type="button" onclick="ToggleConnectionClicked();">连接</button> </form> <div id="LogContainer" class="container"></div> </div> <footer id="SendDataContainer"> <input type="text" id="DataToSend" size="70"> <input type="button" id="SendData" value="发送" onclick="SendDataClicked();"> </footer> </div>
var ws; var SocketCreated = false; var isUserloggedout = false; function lockOn(str) { var lock = document.getElementById('skm_LockPane'); // id="skm_LockPane" 空idv if (lock) // 如果变量lock lock.className = 'LockOn'; lock.innerHTML = str; } function lockOff() { var lock = document.getElementById('skm_LockPane'); lock.className = 'LockOff'; } /* 点击 按钮 */ function ToggleConnectionClicked() { if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) { //(SocketCreated = false)&&(连接未建立)。。。。readyState属性表示ReadOnly属性的状态。等于0或者1表示连接未建立 lockOn("离开聊天室..."); // lockOn 页面秒弹"离开聊天室..." SocketCreated = false; isUserloggedout = true; ws.close(); } else { lockOn("进入聊天室..."); // lockOn 页面秒弹"进入聊天室..." Log("准备连接到服务器 ..."); try { if ("WebSocket" in window) { ws = new WebSocket("ws://" + document.getElementById("Connection").value); } else if ("MozWebSocket" in window) { ws = new MozWebSocket("ws://" + document.getElementById("Connection").value); } SocketCreated = true; isUserloggedout = false; } catch (ex) { Log(ex, "ERROR"); return; } document.getElementById("ToggleConnection").innerHTML = "断开"; ws.onopen = WSonOpen; ws.onmessage = WSonMessage; ws.onclose = WSonClose; ws.onerror = WSonError; } }; function WSonOpen() { lockOff(); Log("连接已建立!", "OK"); $("#SendDataContainer").show(); //输入框显现 console.log(1213); //控制台输出 }; function WSonMessage(event) { Log(event.data); }; function WSonClose() { lockOff(); if (isUserloggedout) Log("【" + document.getElementById("txtName").value + "】离开了聊天室!"); document.getElementById("ToggleConnection").innerHTML = "连接"; $("#SendDataContainer").hide(); }; function WSonError() { lockOff(); Log("远程连接中断", "ERROR"); }; function SendDataClicked() { if (document.getElementById("DataToSend").value.trim() != "") { ws.send(document.getElementById("txtName").value + " 说:" + document.getElementById("DataToSend").value); document.getElementById("DataToSend").value = ""; } }; function Log(Text, MessageType) { if (MessageType == "OK") Text = "<span style='color: green;'>" + Text + "</span>"; if (MessageType == "ERROR") Text = "<span style='color: red;'>" + Text + "</span>"; document.getElementById("LogContainer").innerHTML = document.getElementById("LogContainer").innerHTML + Text + "<br />"; var LogContainer = document.getElementById("LogContainer"); LogContainer.scrollTop = LogContainer.scrollHeight; }; $(document).ready(function () { $("#SendDataContainer").hide(); var WebSocketsExist = true; try { var dummy = new WebSocket("ws://192.168.1.201:2012"); } catch (ex) { try { webSocket = new MozWebSocket("ws://192.168.1.201:2012"); } catch (ex) { WebSocketsExist = false; } } if (WebSocketsExist) { Log("您的浏览器支持WebSocket. 您可以尝试连接到聊天服务器!", "OK"); document.getElementById("Connection").value = "192.168.1.201:2012"; } else { Log("您的浏览器不支持WebSocket。请选择其他的浏览器再尝试连接服务器。", "ERROR"); document.getElementById("ToggleConnection").disabled = true; } $("#DataToSend").keypress(function (evt) { if (evt.keyCode == 13) { $("#SendData").click(); evt.preventDefault(); } }) });
输入用户名之后点击按钮连接到服务器:
因为没有服务器可以连接,所以。。。。O(∩_∩)O哈哈~
在点击断开后,连接断开,用户离开:
前端后台都会的可以玩一下,我刚开始的时候觉得好好玩,一直在那发消息哈哈~
六、 WebSocket 其他 。
1、所谓的 TCP 连接,即三次握手,还记得在学校的时候期末考试这个必考,啊哈哈
过程:(1)客户端发送一个SYN包给服务器,然后等待应答。
(2)服务器端回应给客户端一个ACK=1、SYN=1的 TCP 数据段。
(3)客户必须再次回应服务器端一个ACK确认数据段。
2、WebSocket 和 Http 协议。
WebSocket 和 Http 协议都属于应用层协议。
关系:当 WebSocket 建立握手连接时,数据是通过 HTTP 协议传输的,在建立连接后,真正的数据传输不需要 HTTP 协议参与。
3、WebSocket Server (web 服务器)
调用开源库,如 PyWebSocket(python语言)、WebSocket-Node(js语言,建立在Node.js上)、LibWebSockets(c/c++语言)....他们实现了 WebSocket 数据包的封装和解析,调用这些接口即可。