WebSocket 学习--用nodejs搭建服务器
最简单的socket服务端
- var net = require("net");
- server1 = net.createServer(function(client){
- client.write('Hello World!\r\n');
- });
- server1.listen(9000);
websocket服务端的搭建
前面已经学习了WebSocket API,包括事件、方法和属性。详情:WebSocket(二)--API WebSocket是基于事件驱动,支持全双工通信。下面通过三个简单例子体验一下。
简单开始
1.安装node。https://nodejs.org/en/
2.安装ws模块
ws:是nodejs的一个WebSocket库,可以用来创建服务。 https://github.com/websockets/ws
3.server.js
在项目里面新建一个server.js,创建服务,指定8181端口,将收到的消息log出来。
- var WebSocketServer = require('ws').Server,
- wss = new WebSocketServer({ port: 8181 });
- wss.on('connection', function (ws) {
- console.log('client connected');
- ws.on('message', function (message) {
- console.log(message);
- });
- });
4.建立一个client.html。
在页面上建立一个WebSocket的连接。用send方法发送消息。
- var ws = new WebSocket("ws://localhost:8181");
- ws.onopen = function (e) {
- console.log('Connection to server opened');
- }
- function sendMessage() {
- ws.send($('#message').val());
- }
页面:
- <html xmlns="http://www.w3.org/1999/xhtml">
- <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" />
- <script src="../js/jquery-1.12.3.min.js"></script>
- <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");
- ws.onopen = function (e) {
- console.log('Connection to server opened');
- }
- function sendMessage() {
- ws.send($('#message').val());
- }
- </script>
- </head>
- <body >
- <div class="vertical-center">
- <div class="container">
- <p> </p>
- <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="Type text to echo in here" value="" />
- </div>
- <button type="button" id="send" class="btn btn-primary"
- onclick="sendMessage();">
- Send!
- </button>
- </form>
- </div>
- </div>
- </body>
- </html>
运行之后如下,服务端即时获得客户端的消息。
模拟股票(实例)
上面的例子很简单,只是为了演示如何运用nodejs的ws创建一个WebSocket服务器。且可以接受客户端的消息。那么下面这个例子演示股票的实时更新。客服端只需要连接一次,服务器端会不断地发送新数据,客户端收数据后更新UI.页面如下,有五只股票,开始和停止按钮测试连接和关闭。
服务端:
1.模拟五只股票的涨跌。
- 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 randomStockUpdater = function() {
- 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();
2.连接建立之后就开始更新数据
- wss.on('connection', function (ws) {
- var sendStockUpdates = function (ws) {
- if (ws.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);
- });
客户端:
建立连接:
- var ws = new WebSocket("ws://localhost:8181");
onopen直接只有在连接成功后才会触发,在这个时候将客户端需要请求的股票发送给服务端。
- var isClose = false;
- var stocks = {
- "AAPL": 0, "MSFT": 0, "AMZN": 0, "GOOG": 0, "YHOO": 0
- };
- function updataUI() {
- ws.onopen = function (e) {
- console.log('Connection to server opened');
- isClose = false;
- ws.send(JSON.stringify(stock_request));
- console.log("sened a mesg");
- }
- //更新UI
- var changeStockEntry = function (symbol, originalValue, newValue) {
- var valElem = $('#' + symbol + ' span');
- valElem.html(newValue.toFixed(2));
- if (newValue < originalValue) {
- valElem.addClass('label-danger');
- valElem.removeClass('label-success');
- } else if (newValue > originalValue) {
- valElem.addClass('label-success');
- valElem.removeClass('label-danger');
- }
- }
- // 处理受到的消息
- ws.onmessage = function (e) {
- var stocksData = JSON.parse(e.data);
- console.log(stocksData);
- for (var symbol in stocksData) {
- if (stocksData.hasOwnProperty(symbol)) {
- changeStockEntry(symbol, stocks[symbol], stocksData[symbol]);
- stocks[symbol] = stocksData[symbol];
- }
- }
- };
- }
- updataUI();
运行效果如下:只需要请求一次,数据就会不断的更新,效果是不是很赞,不用轮询,也不用长连接那么麻烦了。文章末尾会附上所有源码。
(美股的涨跌和A股的颜色是反的,即红跌绿涨)
实时聊天
上面的例子是连接建立之后,服务端不断给客户端发送数据。接下来例子是一个简单的聊天室类的例子。可以建立多个连接。
1.安装node-uuid模块,用来给每个连接一个唯一号。
2.服务端消息发送
消息类型分notification和message两种,前者是提示信息,后者是聊天内容。消息还包含一个id、昵称和消息内容。在上一节有学习到readyState有四个值,OPEN表示连接建立可以发送消息。如果页面关闭了,为WebSocket.CLOSE。
- 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({
- "type": type,
- "id": client_uuid,
- "nickname": nickname,
- "message": message
- }));
- }
- }
- }
3.服务端处理连接
每新增加一个连接,都会发送一条匿名用户的加入的提示消息,如果消息中带有“/nick” 认为这一个修改昵称的消息。然后更新客户端的昵称。其他都会当做聊天消息处理。
- 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) {
- 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);
- }
- });
处理连接关闭:
- 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();
- });
4.客户端
没有启动时,页面如下,change按钮用来修改昵称。
- <div class="vertical-center">
- <div class="container">
- <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" 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 class="form-group"><span>nikename:</span><input id="name" type="text" /> <button class="btn btn-sm btn-info" onclick="changName();">change</button></div>
- </div>
- </div>
js:
- //建立连接
- 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);
- }
- }
运行结果:
页面关闭之后,连接马上断开。
这种实时响应的体验简直不能太爽,代码也清爽了,前端体验也更好,客户端不用一直发请求,服务端不用等着被轮询。
小结:上面例子的代码都很好理解,接下来学习WebSocket协议。
源码:http://pan.baidu.com/s/1c2FfKbA
源码:http://pan.baidu.com/s/1o8KRmUQ 加入了socket.io的实现。
API:WebSocket API
相关:websoket使用Protocol Buffers3.0传输
转 :https://www.cnblogs.com/stoneniqiu/p/5402311.html
WebSocket 学习--用nodejs搭建服务器的更多相关文章
- nodejs搭建服务器 和 操作数据库
1.express框架:是一个简洁而灵活的 node.js Web应用框架.一般的项目都是基于这个框架开发的.http://www.runoob.com/nodejs/nodejs-express-f ...
- node学习笔记2——搭建服务器
搭建服务器关键词: require('http') —— 请求 node 里面的 http 模块 createServer —— 创建一个服务器 request —— 请求 response—— 响应 ...
- WebSocket 学习(三)--用nodejs搭建服务器
前面已经学习了WebSocket API,包括事件.方法和属性.详情:WebSocket(二)--API WebSocket是基于事件驱动,支持全双工通信.下面通过三个简单例子体验一下. 简单开始 ...
- 利用nodejs搭建服务器,测试AJAX
最近学习了AJAX一直没有进行过测试,前今天了解了Noejs搭建本地服务器下就尝试了一下.通过AJAX请求的方式获取HTTP服务器返回数据的代码 首先创建一个serve.js的文件.并写入以下代码. ...
- 使用nodejs搭建服务器显示HTML页面
首先安装express 在命令行输入:npm install express -g 安装完成后可以查看安装情况:npm ls -g 然后创建server.js文件 var express = requ ...
- 用nodejs搭建类似于C++的服务器后台.类似网易pomelo
实际的情况,用nodejs跑业务,非常的快,只要用好其无阻塞和回调这两点,处理速度真的是杠杠的. 从年初开始,我用nodejs搭建了类似C++的服务器后台,也想和做同样的事情的朋友分享,本服务平台因为 ...
- NodeJs本地搭建服务器,模拟接口请求,获取json数据
最近在学习Node.js,虽然就感觉学了点皮毛,感觉这个语言还不错,并且也会一步步慢慢的学着的,这里实现下NodeJs本地搭建服务器,模拟接口请求,获取json数据. 具体的使用我就不写了,这个博客写 ...
- NodeJS搭建HTTPS服务器
[NodeJS搭建HTTPS服务器] http://cnodejs.org/topic/54745ac22804a0997d38b32d
- 用nodejs搭建一个简单的服务器
使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...
随机推荐
- Android 开源项目android-open-project解析之(四) ColorPickView,GraphView,UI Style,Other
十三.ColorPickView ColorPickerView 颜色选择器,支持PopupWindows或新的Activity中打开 项目地址:https://code.google.com/p/c ...
- osgi实战学习之路:2. maven+maven-bundle-plugin+karaf搭建osgi之HelloWorld
环境准备: jdk版本号 jdk:1.7 karaf: 版本号:apache-karaf-3.0.1 下载地址: http://pan.baidu.com/s/1qWM4Y1u http://kara ...
- Unity3D协程介绍 以及 使用
作者ChevyRay ,2013年9月28日,snaker7译 原文地址:http://unitypatterns.com/introduction-to-coroutines/ 在Unity中,协 ...
- IDE的文件和代码模板
设置IDE的的模板,可以在创建文件的时候,自动产生模板内容,模板里可以 模板头设置: # -*- coding: utf- -*- """ --------------- ...
- HTML:图片和视频标签的使用
介绍:在html网页中,图片和视频是基本的元素,在网页中插入图片和视频有自己的标签,分别是img.embed,来源都是使用src来链接. 插入图片: <img src="图片的来源&q ...
- Android4.2.2 Gallery2源码分析(5)——GLCanvasImpl.java
GLCanvasImpl.java是接口GLCanvas的唯一实现类,也就是说二者在功能上完全等同.代码中调用GLCanvas对象函数的地方,等效于调用GLCanvasImpl中的该函数,GLCanv ...
- 解决Windows server 2012 R2 系统使用IIS8浏览Asp程序出现"An error occurred on the server when processing the URL"错误
进入IIS并将ASP里的“Send Error To Browser”设置为True后点击Appley保存即可 原因是IIS里的Asp设置禁用上当错误信息发送给浏览器,只要启用即可 如果没有Asp选项 ...
- scala lambda 小括号与大括号
看akka源码的时候看到这样的一个用法: 作为接触scala两天半的我有些看不明白了.好一番搜索看到这样的答案: <scala雾中风景(2): 小括号与花括号> 下面的问题,表面上看是小括 ...
- (剑指Offer)面试题42:翻转单词顺序
题目: 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理. 例如输入字符串“I am a student.”,则输出"student. ...
- C#应用视频教程1.2 Socket通信客户端实现
接下来我们尝试实现最简单的Socket客户端,为了确保只可能你的代码有问题,服务器要先用别人成熟的代码测试(这也是编程的一个技巧,先不要用自己写的客户端测试自己写的服务器,这样出了问题你也不知道谁有问 ...