WebSocket实现web即时通信(后端nodejs实现)

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>

原文地址:https://www.cnblogs.com/Micang/p/9807005.html

时间: 2024-10-26 15:33:34

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

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

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

web即时通信1--WebSocket与WebRTC的三种实现方式对比

转自:http://demo.netfoucs.com/jrn1012/article/details/41982971 最近应项目组要求研究了下WebRTC(目前支持Firefox和Chrome),WebRTC,名称源自网页实时通信(Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的技术,是谷歌2010年以6820万美元收购Global IP Solutions公司而获得的一项技术.WebRTC使得开发者在浏览器无需安装任何插件就可

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

即时通信常用手段 1.第三方平台 谷歌.腾讯 环信等多如牛毛,其中谷歌即时通信是免费的,但免费就是免费的并不好用.其他的一些第三方一般收费的,使用要则限流(1s/限制x条消息)要么则限制用户数. 但稳定性什么都还不错,又能将服务压力甩出 2.System.Net.Sockets.Socket,也能写一套较好的服务器端.在.NET 4.5之前用较多,使用起来麻烦.需要对数据包进行解析等操作(但貌似网上有对超长包的处理方法) 3.System.Net.WebSockets.WebSocket,这个,

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

ChatRoom Node.js+websocket+mongodb实现即时聊天室 A,nodejs简介:Node.js是一个可以让javascript运行在服务器端的平台,它可以让javascript脱离浏览器的束缚运行在一般的服务器下面,你可以用Node.js轻松地进行服务器端应用的开发.Node.js是一个为实时Web应用开发而诞生的平台,它充分考虑了在实时响应和超大规模数据下架构的可扩展性,这使得它摒弃了传统的平台依靠多线程来实现高并发的的设计思路,而采用了单线程,异步式I/O和事件驱动

即时通信常见的几种方式,此处只做学习记录

1. 轮询 利用ajax每隔一段时间就请求一次服务器,服务器返回数据. 优点:最简单的解决方案 缺点:对服务器压力很大,浪费带宽 2. 长轮询 利用ajax请求服务器,当有数据变化的时候,立刻返回,当没有数据的时候,保持这个连接直到 断开,当断开的时候再次发出请求,一直循环 优点:最简单的解决方案,减少了对服务器的请求次数 缺点:对服务器压力大,同样浪费带宽(在保持连接的时候(hold),会消耗资源) 3. 长连接 在页面里面嵌套一个iframe,设置src为一个长连接的请求,服务器就能不断向客

结束QQ即时通信垄断,开辟即时通信互联互通instantnet时代

蓬勃发展的即时通信产业 即时通信(IM)是指能够即时发送和接收互联网消息等的业务. 即时通信,就是瞬间把信息发送给对方,如果不是即时发送的,我们就说离线的,email邮件式的,不是立即看见的. 即时通信开始是短消息的,也可以发长文件,微博也是短消息的,传文件我们一般不叫即时通信. 不过即时通信已经发展成集交流.资讯.娱乐.搜索.电子商务.办公协作和企业客户服务等为一体的综合化信息平台. 这样即时通信范围就大了,但是这时候已经是一个综合化信息平台,不是单纯的发送消息. 我们目前还是定位在即时通信就

基于XMPP协议的Android即时通信系

以前做过一个基于XMPP协议的聊天社交软件,总结了一下.发出来. 设计基于开源的XMPP即时通信协议,采用C/S体系结构,通过GPRS无线网络用TCP协议连接到服务器,以架设开源的Openfn'e服务器作为即时通讯平台. 系统主要由以下部分组成:一是服务器,负责管理发出的连接或者与其他实体的会话,接收或转发XML(ExtensibleMarkup Language)流元素给授权的客户端.服务器等:二是客户终端.它与服务器相连,通过XMPP获得由服务器或任何其它相关的服务所提供的全部功能.三是协议

(转)基于即时通信和LBS技术的位置感知服务(二):XMPP协议总结以及开源解决方案

在<基于即时通信和LBS技术的位置感知服务(一):提出问题及解决方案>一文中,提到尝试使用XMPP协议来实现即时通信.本文将对XMPP协议框架以及相关的C/S架构进行介绍,协议的底层实现不再本文的讨论范围. 一.什么是XMPP? 介 绍XMPP之前,我们先来聊聊GTalk.GTalk是Google推出的IM(Instant Messaging,即时通讯)软件,类似于QQ和MSN.从技术角度来说,GTalk与QQ和MSN的差异是使用了不同的通讯协议,QQ使用了自己的私 有协议(未公开),MSN也

(转)基于即时通信和LBS技术的位置感知服务(一):提出问题及解决方案

一.前言.提出问题 公司最近举行2011年度创新设计大赛,快年底了正打算写写2010年以来Android开发的心得与经验,正好同事出了个点子:假如A和B两个人分别在不同的地点,能不能实现这样的功能,让A和B之间可以互相感知对方的位置信息. 于是整理了一下思绪,说白了分解开来就是两个方面的问题:一.实现信息的即时传递,二.实现基站/wifi.GPS的定位. 1. 实现消息的即时传递:说到这个问题大家应该能联想到QQ.MSN.Gtalk这些即时通信软件. 2. 定位:这个让人联想到时下非常火的LBS