珠海网站建设培训学校,中国世界排名第几?,郑州做花店网站,网站开发技术选型websocket简介#xff1a;
WebSocket协议是 HTML5 开始提供的一种基于TCP的一种新的全双工通讯的网络通讯协议。它允许服务器主动发送信息给客户端。 和http协议的不同#xff1f;#xff1f;
HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型…websocket简介
WebSocket协议是 HTML5 开始提供的一种基于TCP的一种新的全双工通讯的网络通讯协议。它允许服务器主动发送信息给客户端。 和http协议的不同
HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起服务端对请求做出应答处理。这种通信模型有一个弊端HTTP 协议无法实现服务器主动向客户端发起消息。而这种单向请求的特点注定了如果服务器有连续的状态变化客户端要获知就非常麻烦。
简单的说WebSocket协议之前实现双工通信就是通过不停发送HTTP请求长轮询使用 Ajax 轮询技术轮询是在特定的的时间间隔如每1秒由浏览器对服务器发出HTTP请求从服务器拉取更新来实现这导致了效率低下浪费带宽资源WebSocket解决了这个问题。
WebSocket 就是这样发明的。WebSocket 连接允许客户端和服务器之间进行全双工通信以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。 websocket如何工作 在实现websocket连线过程中需要通过浏览器发出websocket连线请求然后服务器发出回应这个过程通常称为握手 。在 WebSocket API 中浏览器和服务器只需要完成一次握手两者之间就直接可以创建持久性的连接并进行双向数据传输相传送。 浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求连接建立以后客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后你可以通过 send() 方法来向服务器发送数据并通过 onmessage 事件来接收服务器返回的数据。 以下 API 用于创建 WebSocket 对象。第一个参数 url, 指定连接的 URL。而URL参数需要以WS://或者WSS://开头例如ws://www.websocket.org如果URL有语法错误构造函数会抛出异常。第二个参数 protocol 是可选的指定了可接受的子协议。议的参数例如XMPPExtensible Messaging and Presence Protocol、SOAPSimple Object Access Protocol或者自定义协议。 第二个参数是协议名称是可选的服务端和客服端使用的协议必须一致这样收发消息彼此才能理解你可以定义一个或多个客户端使用的协议服务端会选择一个来使用一个客服端和一个服务端之间只能有一个协议。
var Socket new WebSocket(url, [protocol] );
注意基于多线程或多进程的服务器无法适用于 WebSockets因为它旨在打开连接尽可能快地处理请求然后关闭连接。任何实际的 WebSockets 服务器端实现都需要一个异步服务器。
目前大部分浏览器支持 WebSocket() 接口如 Chrome, Mozilla, Opera 和 Safari。 WS和WSS的区别
注意WebSocket协议定义了两种URL方案WS和WSS分别代表了客户端和服务端之间未加密和加密的通信。WS(WebSocket)类似于Http URL而WSSWebSocket SecurityURL 表示连接是基于安全传输层TLS/SSL和https的连接是同样的安全机制。 websocket的属性、事件、方法
属性描述Socket.readyState 只读属性 readyState 表示连接状态可以是以下值 0 - 表示连接尚未建立。 1 - 表示连接已建立可以进行通信。 2 - 表示连接正在进行关闭。 3 - 表示连接已经关闭或者连接不能打开。 Socket.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输但是还没有发出的 UTF-8 文本字节数。
注意上述readyState 属性用于表示链接状态 事件事件处理程序描述openSocket.onopen连接建立时触发messageSocket.onmessage客户端接收服务端数据时触发errorSocket.onerror通信发生错误时触发closeSocket.onclose连接关闭时触发方法描述Socket.send() 使用连接发送数据 Socket.close() 关闭连接 websocketnodejs简单实例应用
WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接客户端浏览器首先要向服务器发起一个 HTTP 请求这个请求和通常的 HTTP 请求不同包含了一些附加头信息其中附加头信息Upgrade: WebSocket表明这是一个申请协议升级的 HTTP 请求服务器端解析这些附加的头信息然后产生应答信息返回给客户端客户端和服务器端的 WebSocket 连接就建立起来了双方就可以通过这个连接通道自由的传递信息并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
WebSocket API是纯事件驱动一旦建立全双工连接当服务端给客户端发送数据或者资源它能自动发送状态改变的数据和通知。所以你不需要为了状态的更新而去轮训Server在客户端监听即可。 websocket客户端
!DOCTYPE HTML
htmlheadmeta charsetutf-8titlewebsocket测试(runoob.com)/titlescript typetext/javascriptfunction WebSocketTest(){if (WebSocket in window){alert(您的浏览器支持 WebSocket!);// 初始化一个 WebSocket 对象参数指明urlvar ws new WebSocket(ws://localhost:9999);// WebSocket 连接时候触发ws.onopen function(){//使用 send() 方法发送数据ws.send(客户端发送的数据);alert(数据发送中...);};// 接收服务端数据时触发ws.onmessage function (evt) { var received_msg evt.data;console.log(received_msg);alert(数据已接收...);};//断开 web socket 连接成功触发事件ws.onclose function(){ // 关闭 websocketalert(连接已关闭...); };}else{// 浏览器不支持 WebSocketalert(您的浏览器不支持 WebSocket!);}}/script/headbodydiv idssea hrefjavascript:WebSocketTest()运行 WebSocket/a/div/body
/html websocket服务端
WebSocket 在服务端的实现非常丰富。Node.js、Java、C、Python 等多种语言都有自己的解决方案。这里主要记录nodejs作为websocket服务端的解决方案。
Node 实现有以下三种。
µWebSocketsSocket.IOWebSocket-Node这里主要记录使用nodejs搭建websocket服务器的方案
ws 是nodejs的一个WebSocket库可以用来创建服务。使用cnpm install ws 命令行进行安装
下面是server.js的文件内容cmd转到文件目录运行 node server.js 命令行 var WebSocketServer require(ws).Server,
wss new WebSocketServer({ port: 9999 });
wss.on(connection, function (ws) {console.log(client connected);ws.on(message, function (message) {console.log(message);ws.send(服务端接收到请求后发送给客户端的数据);});});
效果如下 进阶websocketnodejs模拟股票实例
上面的例子很简单只是为了演示如何运用nodejs的ws创建一个WebSocket服务器。且可以接受客户端的消息。那么下面这个例子演示股票的实时更新。客服端只需要连接一次服务器端会不断地发送新数据客户端收数据后更新UI.页面如下有五只股票开始和停止按钮测试连接和关闭。
注意一定要先在项目文件夹下运行 cnpm install ws 安装wwebsocket依赖包不然会报以下错误 服务端server.js文件内容如下
//引入websocket 的ws模块
var WebSocketServer require(ws).Server,//初始化websocket对象
wss new WebSocketServer({ port: 8181 });//初始数据对象
var stocks {AAPL: 95.0,MSFT: 50.0,AMZN: 300.0,GOOG: 550.0,YHOO: 35.0
}//获取随机数据的函数
function randomInterval(min, max) {return Math.floor(Math.random() * (max - min 1) min);
}//定时器返回的句柄
var stockUpdater;
var randomStockUpdaterfunction(){for (var symbol in stocks) { //遍历对象属性进行随机增加浮动数值if(stocks.hasOwnProperty(symbol)) { //遍历对象非继承属性var randomizedChange randomInterval(-150, 150);var floatChange randomizedChange / 100;stocks[symbol] floatChange;}}//随机时间间隔获取一个数据区间中的随机数值var randomMSTime randomInterval(500, 2500); stockUpdater setTimeout(function() { //模拟股票数据变化随机更改对象属性值randomStockUpdater();}, randomMSTime);}//执行模拟数据变化更新
randomStockUpdater();//声明clientStocks接收客户端数据
var clientStocks [];//连接建立后
wss.on(connection, function (ws) {//定义数据更新函数var sendStockUpdates function (ws) {if (ws.readyState 1) { //readyState为1表示已经建立连接var stocksObj {};for (var i 0; i clientStocks.length; i) {var symbol clientStocks[i];stocksObj[symbol] stocks[symbol];}if (stocksObj.length ! 0) { //数据包内容不为空时将数据响应给客户端ws.send(JSON.stringify(stocksObj));//需要将对象转成字符串。WebSocket只支持文本和二进制数据console.log(更新, JSON.stringify(stocksObj));}}}//服务器端定时更新响应数据var clientStockUpdater setInterval(function () {sendStockUpdates(ws);}, 1000);//服务器端接收到客户端发送过来的数据根据请求的数据更新响应数据ws.on(message, function (message) {var stockRequest JSON.parse(message);console.log(服务器收到的消息, stockRequest);clientStocks stockRequest[stocks];sendStockUpdates(ws);});}); 客户端client.html 文件如下界面使用了和jquery和bootstrape框架
html xmlnshttp://www.w3.org/1999/xhtml
headmeta http-equivContent-Type contenttext/html; charsetutf-8 /titleWebSocket Demo/titlemeta nameviewport contentwidthdevice-width, initial-scale1/link href../bootstrap-3.3.5/css/bootstrap.min.css relstylesheet /script src../js/jquery-1.12.3.min.js/scriptscript src../bootstrap-3.3.5/js/bootstrap.min.js/script
/headbody
div classvertical-centerdiv classcontainerh1Stock Chart over WebSocket/h1button classbtn btn-primary开始/buttonbutton classbtn btn-danger停止/buttontable classtable idstockTabletheadtrthSymbol/ththPrice/th/tr/theadtbody idstockRowstrtdh3AAPL/h3/tdtd idAAPLh3span classlabel label-default95.00/span/h3/td/trtrtdh3MSFT/h3/tdtd idMSFTh3span classlabel label-default50.00/span/h3/td/trtrtdh3AMZN/h3/tdtd idAMZNh3span classlabel label-default300.00/span/h3/td/trtrtdh3GOOG/h3/tdtd idGOOGh3span classlabel label-default550.00/span/h3/td/trtrtdh3YHOO/h3/tdtd idYHOOh3span classlabel label-default35.00/span/h3/td/tr/tbody/table/div
/divscript//客户端初始化websocket对象var ws new WebSocket(ws://localhost:9999);//客户端发送的请求对象var stock_request { stocks: [AAPL, MSFT, AMZN, GOOG, YHOO] };var isClose false; //通讯连接是否被关闭//界面的初始化数据对象var stocks {AAPL: 0, MSFT: 0, AMZN: 0, GOOG: 0, YHOO: 0};//定义更新UI界面的函数function updataUI() {//websocket连接上时触发ws.onopen function (e) {console.log(Connection to server opened);isClose false;ws.send(JSON.stringify(stock_request));console.log(sened a mesg);}// UI update functionvar changeStockEntry function (symbol, originalValue, newValue) {var valElem $(# symbol span);valElem.html(newValue.toFixed(2)); //toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。if (newValue originalValue) {valElem.addClass(label-danger);valElem.removeClass(label-success);} else if (newValue originalValue) {valElem.addClass(label-success);valElem.removeClass(label-danger);}}// websocket接收到服务端数据时触发ws.onmessage function (e) {var stocksData JSON.parse(e.data); //字符串转JSON对象console.log(stocksData);for (var symbol in stocksData) { //遍历对象属性更改客户端界面数据if (stocksData.hasOwnProperty(symbol)) {changeStockEntry(symbol, stocks[symbol], stocksData[symbol]);stocks[symbol] stocksData[symbol];}}};}updataUI(); //更新UI界面$(.btn-primary).click(function() { //开始按钮点击可以在断开后重连websocketif (isClose) {ws new WebSocket(ws://localhost:9999);}updataUI(); //重连后更新UI界面});$(.btn-danger).click(function() { //断开按钮可以关闭websocket连接ws.close();});//触发websocket连接关闭事件ws.onclose function (e) {console.log(Connection closed, e);isClose true;};/script
/body
/html
源码见文章底部链接效果如下 进阶websocketnodejs模拟聊天室实例 上面的例子是连接建立之后服务端不断给客户端发送数据。接下来例子是一个简单的聊天室类的例子。可以建立多个连接。
1.安装node-uuid模块用来给每个连接一个唯一号。 2、客户端代码如下
html xmlnshttp://www.w3.org/1999/xhtml
headmeta http-equivContent-Type contenttext/html; charsetutf-8 /titleWebSocket Echo Demo/titlemeta nameviewport contentwidthdevice-width, initial-scale1/link href../bootstrap-3.3.5/css/bootstrap.min.css relstylesheet /script src../js/jquery-1.12.3.min.js/scriptscript src../js/jquery-1.12.3.min.js/scriptscript src../bootstrap-3.3.5/js/bootstrap.min.js/scriptscript//建立连接var ws new WebSocket(ws://localhost:8181);var nickname ;ws.onopen function (e) {console.log(Connection to server opened);}//显示函数根据客户端接收到的数据类型进行ui界面显示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 nbsp;nbsp; 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
/headbody div classvertical-centerdiv classcontainerul idmessages classlist-unstyled/ulhr/form roleform idchat_form onsubmitsendMessage(); return false;div classform-groupinput classform-control typetext idmessage namemessageplaceholderType text to echo in here value autofocus//divbutton typebutton idsend classbtn btn-primaryonclicksendMessage();Send Message/button/formdiv classform-groupspannikename/spaninput idname typetext / button classbtn btn-sm btn-info onclickchangName();change/button/div/div/div
/body
/html 3、服务端代码如下
//引入ws模块初始化websocket服务端
var WebSocket require(ws);
var WebSocketServer WebSocket.Server,
wss new WebSocketServer({ port: 8181 });//引入node-uuid模块唯一标识
var uuid require(node-uuid);//客户端数组
var clients [];//遍历所有客户端连接依次下发数据
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) {clientSocket.send(JSON.stringify({ //websocket传递JSONA字符串格式type: type,id: client_uuid,nickname: nickname,message: message}));}}
}var clientIndex 1;//每一个客户端和服务端建立连接时触发
wss.on(connection, function(ws) {var client_uuid uuid.v4(); //获取随机唯一标识var nickname AnonymousUser clientIndex;clientIndex 1;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);console.log(client [%s] connected, client_uuid);ws.on(message, function(message) {if (message.indexOf(/nick) 0) { //json字符串数据包含修改昵称的数据时var nickname_array message.split( );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);}});//断开指定uuid的连接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();});//SIGINT这个信号是系统默认信号代表信号中断就是ctrlcprocess.on(SIGINT, function () {console.log(Closing things);closeSocket(Server has disconnected);process.exit();});
});
效果如下 源码见文章尾部 上述代码实现了一个服务器下的多个客户端连接单并没有实现客户端的及时通讯比如微信和QQ的单聊和群聊效果可以参考以下demo
参考网址https://blog.csdn.net/CJXBShowZhouyujuan/article/details/77816944 node-uuid是什么 nodejs生成UID唯一标识符——node-uuid模块
unique identifier 惟一标识符 -- uid
在项目开发中我们常需要给某些数据定义一个唯一标识符便于寻找关联。node-uuid模块很好的提供了这个功能。 使用起来很简单两种
1、uuid.v1(); --基于时间戳生成 time-based
2、uuid.v4(); --随机生成 (random) 通常我们使用基于时间戳 v1() 生成的UID随机生成 v4() 还是有一定几率重复的。 var UUID require(uuid);var ID UUID.v1(); websocket 和 socket 的区别
软件通信有七层结构下三层结构偏向与数据通信上三层更偏向于数据处理中间的传输层则是连接上三层与下三层之间的桥梁每一层都做不同的工作上层协议依赖与下层协议。基于这个通信结构的概念。
Socket 其实并不是一个协议是应用层与 TCP/IP 协议族通信的中间软件抽象层它是一组接口。当两台主机通信时让 Socket 去组织数据以符合指定的协议。TCP 连接则更依靠于底层的 IP 协议IP 协议的连接则依赖于链路层等更低层次。
WebSocket 则是一个典型的应用层协议。
总的来说Socket 是传输控制层协议WebSocket 是应用层协议。 源码http://pan.baidu.com/s/1c2FfKbA
或 百度链接https://pan.baidu.com/s/1cabjJKikHC3xBW-qUtP-3g 提取码yb4u
参考网址
https://www.cnblogs.com/stoneniqiu/p/5402311.html
http://www.runoob.com/html/html5-websocket.html