WebSocket实现web即时通信

一、首先看一下,HTTP、ajax轮询、long poll和WebSocket的区别:

1、HTTP 协议(短连接):一个 Request 一个 Response。缺陷:通信只能由客户端发起。
--------------------------------------------------------------------------------
2、ajax轮询:
ajax轮询的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)
--------------------------------------------------------------------------------
3、long poll:原理跟ajax轮询差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。基于事件的触发,一个事件接一个事件。long poll需要很高的并发,体现了同时容纳请求的能力。
--------------------------------------------------------------------------------
4、WebSocket:是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。WebSocket的优势在于他的高实时性,以及传输过程中的低的资源消耗!
握手成功后,数据就直接从 TCP 通道传输,与 HTTP 无关了。Websocket的数据传输是frame形式传输的。
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

关于WebSocket的更多介绍可以参考
阮一峰——WebSocket 教程http://www.ruanyifeng.com/blog/2017/05/websocket.html

===============================================================================
二、通过nodejs和javascript实现一个网页聊天室

(参考:博客https://blog.csdn.net/u010136741/article/details/51612594?utm_source=copy;作者:柳木木_kylin )
主要包括,聊天,改用户名,查看其他用户在线状态的功能。
大致流程为,用户访问网页,即进入聊天状态,成为新游客,通过底部的输入框,可以输入自己想说的话,点击发布,信息呈现给所有在聊天的人的页面。用户可以实时修改自己的昵称,用户离线上线都会实时广播给其他用户!
javascript 部分,连接websocket成功之后,主要是监听数据返回,和发送数据。
当用户编辑好内容,点击发送按钮是调用sendMessage方法,发送数据,如果需要修改昵称,则发送数据格式为"/nick 昵称"。
当服务器返回数据到客户端,我们通过appendLog方法对数据做处理,根据type字段,判断是显示用户离线在线信息,还是显示聊天信息。最后更新在线人数。

服务器端:WebSocket_chart_server.js

var WebSocket = require('ws');
var WebSocketServer = WebSocket.Server,
wss = new WebSocketServer({port: 8180});
var uuid = require('node-uuid'); var clients = []; function wsSend(type, client_uuid, nickname, message,clientcount) {
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,
"clientcount":clientcount,
}));
}
}
} var clientIndex = 1; wss.on('connection', function(ws) {
var client_uuid = uuid.v4();
var nickname = "游客"+clientIndex;
clientIndex+=1;
clients.push({"id": client_uuid, "ws": ws, "nickname": nickname});
console.log('client [%s] connected', client_uuid); var connect_message = nickname + " 来了";
wsSend("notification", client_uuid, nickname, connect_message,clients.length); 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 = "用户 " + old_nickname + " 改名为: " + nickname;
wsSend("nick_update", client_uuid, nickname, nickname_message,clients.length);
}
} else {
wsSend("message", client_uuid, nickname, message,clients.length);
}
}); 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 + " 走了";
} clients.splice(i, 1);
wsSend("notification", client_uuid, nickname, disconnect_message,clients.length);
}
}
}
ws.on('close', function() {
closeSocket();
}); process.on('SIGINT', function() {
console.log("Closing things");
closeSocket('Server has disconnected');
process.exit();
});
});

web端:WebSocket_chart_web.html

<!DOCTYPE html>
<html lang="cn">
<head>
<title>WebSocket chart application</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.css">
<link rel="stylesheet" href="http://cdn.bootcss.com/tether/1.3.2/css/tether.css"/>
<script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.js" ></script>
<script src="http://cdn.bootcss.com/tether/1.3.2/js/tether.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/js/bootstrap.js"></script>
<script>
var ws= new WebSocket('ws://localhost:8180');
var nickname;
ws.onopen = function(e){
console.log('Connection to server opened');
}
function appendLog(type,nickname, message,clientcount) {
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);
var count_people = document.getElementById("count_people");
count_people.innerHTML = clientcount; }
ws.onmessage = function(e){
var data = JSON.parse(e.data);
nickname = data.nickname;
appendLog(data.type,data.nickname, data.message,data.clientcount);
console.log("ID: [%s] = %s", data.id, data.message); }
function sendMessage(){
var message = $('#message').val().trim();
if(message.length<1){
alert("不能发送空内容!");
return;
}
ws.send($('#message').val());
$('#message').val("");
$('#message').focus();
console.log(ws.bufferedAmount);
}
</script>
</head>
<body lang="cn">
<div class="vertical-center">
<div class="container">
<h2>多人在线聊天DEMO</h2>
<hr />
<p>当前在线人数:<span id="count_people">0</span></p>
<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" name="message" id="message"
placeholder="输入聊天内容" value="" autofocus/>
</div>
<button type="button" id="send" class="btn btn-primary"
onclick="sendMessage();">发送!</button>
</form>
</div>
</div>
</body>
</html>

WebSocket实现web即时通信(后端nodejs实现)的更多相关文章

  1. WEB即时通信

    问题 传统的浏览器通信方式:基于HTTP协议的请求/响应模式. 早期:通过刷新浏览器来更新服务器端的数据 后来Ajax(XMLHttpRequest是核心):可以不用刷新浏览器更新服务器端数据.但是这 ...

  2. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  3. .NET实现WebSocket服务端即时通信实例

    即时通信常用手段 1.第三方平台 谷歌.腾讯 环信等多如牛毛,其中谷歌即时通信是免费的,但免费就是免费的并不好用.其他的一些第三方一般收费的,使用要则限流(1s/限制x条消息)要么则限制用户数. 但稳 ...

  4. WebSocket实现Web端即时通信

    前言 WebSocket 是HTML5开始提供的一种在浏览器和服务器间进行全双工通信的协议.目前很多没有使用WebSocket进行客户端服务端实时通信的web应用,大多使用设置规则时间的轮询,或者使用 ...

  5. 即时通信WebSocket 和Socket.IO

    WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯. 在2008年诞生,2011年成为国际标准. 现在基本所有浏览器都已经支持了. We ...

  6. .NET 即时通信,WebSocket服务端实例

    即时通信常用手段 1.第三方平台 谷歌.腾讯 环信等多如牛毛,其中谷歌即时通信是免费的,但免费就是免费的并不好用.其他的一些第三方一般收费的,使用要则限流(1s/限制x条消息)要么则限制用户数. 但稳 ...

  7. .NET 即时通信,WebSocket

    .NET 即时通信,WebSocket 即时通信常用手段 1.第三方平台 谷歌.腾讯 环信等多如牛毛,其中谷歌即时通信是免费的,但免费就是免费的并不好用.其他的一些第三方一般收费的,使用要则限流(1s ...

  8. 基于Nodejs开发的web即时聊天工具

    由于公司需要开发web即时聊天的功能,开始时我们主要的实施方法是用jquery的ajax定时(10秒)轮询向服务器请求,由于是轮询请求,对 服务器的压力比较大.我们网站上线的时间不长,访问量不是很大, ...

  9. Node.js+websocket+mongodb实现即时聊天室

    ChatRoom Node.js+websocket+mongodb实现即时聊天室 A,nodejs简介:Node.js是一个可以让javascript运行在服务器端的平台,它可以让javascrip ...

随机推荐

  1. i=i+1,i+=1,i++哪个执行效率最高?为什么?

    (1)i=i+1最低,它的执行过程如下:读取右i的地址i+1读取左i的地址将右值传给左边的i(编译器并不认为左右i的地址相同)(2)i+=1其次,它的执行过程如下:读取左x的地址i+1将得到的值传给i ...

  2. Thrift 基础(C++ rpc )

    一.thrift简介 thrift是Facebook开源的一套rpc框架,目前被许多公司使用 我理解的特点 使用IDL语言生成多语言的实现代码,程序员只需要实现自己的业务逻辑 支持序列化和反序列化操作 ...

  3. 【从0到1学Web前端】CSS定位问题二(float和display的使用) 分类: HTML+CSS 2015-05-28 22:03 812人阅读 评论(1) 收藏

    display 属性规定元素应该生成的框的类型. 这个属性用于定义建立布局时元素生成的显示框类型.对于 HTML 等文档类型,如果使用 display 不谨慎会很危险,因为可能违反 HTML 中已经定 ...

  4. Android_ 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法

    转载时注明地址:http://blog.csdn.net/xiaanming/article/details/9344703 我们开发Android应用的时候,当出现Crash的时候,系统弹出一个警告 ...

  5. Git学习系列之CentOS上安装Git详细步骤(图文详解)

    前言 最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Win ...

  6. 全网最详细的Sublime Text 3的激活(图文详解)

    不多说,直接上干货! 前期博客 全网最详细的Windows里下载与安装Sublime Text *(图文详解) ZYNGA INC. User License EA7E- 927BA117 84C93 ...

  7. Linux MBR扇区误删恢复

    目录 1. 引导记录误删恢复 1.1 备份引导记录 1.2 误删引导记录 1.3 恢复引导记录 2. 分区表误删恢复 2.1 备份分区表 2.2 误删分区表 2.3 恢复分区表 如果MBR分区表没了, ...

  8. Mac OS X 下搭建thrift环境

    1.概述 thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生产引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, ...

  9. linux解决病毒系列之一,删除十字符libudev.so病毒文件

    前两天被服务器商通知服务器带宽流量增加,我想了想我们服务走的内网,没有什么大的带宽占用,于是我马上登录服务器. 用top命令查看运行情况,我擦,有一个进程吃了很高的cup,于是我赶紧用kill -9 ...

  10. docker-使用ali云加速

    ali专用网络加速地址; https://yq.aliyun.com/articles/29941 使用ali加速 vim /etc/sysconfig/docker 添加: ADD_REGISTRY ...