精华内容
下载资源
问答
  • web即时通讯框架
    千次阅读
    2021-05-06 11:52:13

    web端四种即时通讯

    • 轮询

    • 长轮询

    • 长连接

    • websocket

    Web端即时通讯技术:即时通讯技术简单的说就是实现这样一种功能:服务器端可以即时地将数据的更新或变化反应到客户端,例如消息即时推送等功能都是通过这种技术实现的。但是在Web中,由于浏览器的限制,实现即时通讯需要借助一些方法。这种限制出现的主要原因是,一般的Web通信都是浏览器先发送请求到服务器,服务器再进行响应完成数据的现实更新。“

    实现Web端即时通讯的方法:实现即时通讯主要有四种方式,它们分别是轮询、长轮询(comet)、长连接(SSE)、WebSocket。它们大体可以分为两类,一种是在HTTP基础上实现的,包括短轮询、comet和SSE;另一种不是在HTTP基础上实现是,即WebSocket。下面分别介绍一下这四种轮询方式,以及它们各自的优缺点。

    轮询

    短轮询的基本思路就是浏览器每隔一段时间向浏览器发送http请求,服务器端在收到请求后,不论是否有数据更新,都直接进行响应。这种方式实现的即时通信,本质上还是浏览器发送请求,服务器接受请求的一个过程,通过让客户端不断的进行请求,使得客户端能够模拟实时地收到服务器端的数据的变化。

    这种方式的优点是比较简单,易于理解,实现起来也没有什么技术难点。缺点是显而易见的,这种方式由于需要不断的建立http连接,严重浪费了服务器端和客户端的资源。尤其是在客户端,距离来说,如果有数量级想对比较大的人同时位于基于短轮询的应用中,那么每一个用户的客户端都会疯狂的向服务器端发送http请求,而且不会间断。人数越多,服务器端压力越大,这是很不合理的。

    因此短轮询不适用于那些同时在线用户数量比较大,并且很注重性能的Web应用。

    var xhr = new XMLHttpRequest();
    setInterval(function(){
    xhr.open(‘GET’,’/user’);
    xhr.onreadystatechange = function(){

    var xhr = new XMLHttpRequest();
        setInterval(function(){
            xhr.open('GET','/user');
            xhr.onreadystatechange = function(){
    
            };
            xhr.send();
        },1000)
    

    长轮询

    ajax实现:

    当服务器收到客户端发来的请求后,服务器端不会直接进行响应,而是先将这个请求挂起,然后判断服务器端数据是否有更新。如果有更新,则进行响应,如果一直没有数据,则到达一定的时间限制(服务器端设置)才返回。 。 客户端JavaScript响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。

    长轮询和短轮询比起来,明显减少了很多不必要的http请求次数,相比之下节约了资源。长轮询的缺点在于,连接挂起也会导致资源的浪费。

    function ajax(){
            var xhr = new XMLHttpRequest();
            xhr.open('GET','/user');
            xhr.onreadystatechange = function(){
                  ajax();
            };
            xhr.send();
        }
    

    轮询与长轮询都是基于HTTP的,两者本身存在着缺陷:轮询需要更快的处理速度;长轮询则更要求处理并发的能力;两者都是“被动型服务器”的体现:服务器不会主动推送信息,而是在客户端发送ajax请求后进行返回的响应。而理想的模型是"在服务器端数据有了变化后,可以主动推送给客户端",这种"主动型"服务器是解决这类问题的很好的方案。Web Sockets就是这样的方案。

    长连接(sse)

    SSE是HTML5新增的功能,全称为Server-Sent Events。它可以允许服务推送数据到客户端。SSE在本质上就与之前的长轮询、短轮询不同,虽然都是基于http协议的,但是轮询需要客户端先发送请求。而SSE最大的特点就是不需要客户端发送请求,可以实现只要服务器端数据有更新,就可以马上发送到客户端。

    SSE的优势很明显,它不需要建立或保持大量的客户端发往服务器端的请求,节约了很多资源,提升应用性能。并且后面会介绍道,SSE的实现非常简单,并且不需要依赖其他插件。

    websocket

    WebSocket是Html5定义的一个新协议,与传统的http协议不同,该协议可以实现服务器与客户端之间全双工通信。简单来说,首先需要在客户端和服务器端建立起一个连接,这部分需要http。连接一旦建立,客户端和服务器端就处于平等的地位,可以相互发送数据,不存在请求和响应的区别。

    WebSocket的优点是实现了双向通信,缺点是服务器端的逻辑非常复杂。现在针对不同的后台语言有不同的插件可以使用。

    比较

    从兼容性角度考虑,短轮询>长轮询>长连接SSE>WebSocket;

    从性能方面考虑,WebSocket>长连接SSE>长轮询>短轮询

    更多相关内容
  • WEB即时通讯框架

    2017-06-26 16:28:49
    一个纯JS的即时通讯框架,自动兼容IE8+ 亲测可用
  • C#Web即时通讯Comet框架

    2017-10-30 17:08:29
    使用Comet技术实现HTML长连接,对Comet框架进行了一定的封装,允许对发送的结果进行自定义扩展,并实现Web即时通讯的例子
  • 一个Nutz为后台支撑,T-io为通讯支持,LayIM为前台UI交互的纯国产框架开发的一个即时通讯项目
  • 基于SpringBoot开发的Java web在线聊天系统,基于IDEA开发

    目录

    简介

    主要实现的功能有:

    主要功能截图

    温馨提示


    简介

    今天发布的是一款由Springboot+MySQL+SSM实现的Java web在线聊天系统,适合大家在网上聊天,加好友等操作,极大的方便了大家的通信效率。该系统部署简单,功能强大,适合广大开发这和初学者去学习。

    主要实现的功能有:

    前台:

    1、用户注册、登录。

    2、搜索用户添加好友。

    3、查看好友申请列表,同意或拒绝好友请求。

    4、成为好友后单人一对一聊天。

    5、可创建群聊进行聊天。

    除了上述基本的聊天功能外,还有:消息提醒方式设置(可设置是否弹框、是否声音提醒等,提供可选六种新消息提示音)、聊天记录清空、拉黑好友、删除好友、解散群聊、隐身、在线状态设置、好友上下线提醒等等,功能非常的全。重点:聊天信息中可发送文字、图片、文件、视频、音乐、表情包等。

    后台:

    1、后台菜单、角色、管理员的管理。

    2、后台聊天信息、在线用户等统计。

    3、后台日志管理、数据备份等。

    4、用户管理:用户信息查看、状态冻结等。

    5、群聊管理:成员查看、移除成员、解散群聊等。

    6、消息管理:消息详细信息跟踪查看等。

    主要功能截图

    温馨提示

    有需要改系统的同学可以加我企鹅🐧1094576817,提供源码,SQL文件,论文文档,可以帮忙部署项目,由于开发需要成本,需要您提供一点支持,白嫖勿扰。

    此外可以接定制web系统,有需要的朋友可以直接联系我。

    展开全文
  • IM即时通讯项目框架分析

    千次阅读 2022-02-19 00:05:55
    推荐一个零声学院免费...1. 即时通讯框架分析和部署 2. 登录服务器和消息服务器设计 3. 路由服务器设计 4. 数据库代理服务器设计 5. 文件服务器和docker部署 6. 性能测试和k8s上云发布 1.1 即时通讯应用场景 即时通讯

    1 IM即时通讯项目框架分析和部署

    1. 即时通讯框架分析和部署
    2. 登录服务器和消息服务器设计
    3. 路由服务器设计
    4. 数据库代理服务器设计
    5. 文件服务器和docker部署
    6. 性能测试和k8s上云发布

    1.1 即时通讯应用场景

    即时通讯技术应用非常广泛,涉及教育、电商、金融、泛娱乐、生活服务、医疗健康、
    政企服务、游戏聊天、在线客服等等行业,以下以部分典型应用作为简介。
    
    (一)教育 (二)电商 (三)金融 (四)泛娱乐
    
    (五)招聘 (六)医疗健康 (七)政企服务 (八)游戏类产品
    
    提供:即时通讯、用户点对点聊天、主播互动、实时弹幕、
    实时监控、远程控制、多人互动、位置共享
    

    1.2 即时通讯提供商

    容联
    融云
    环信 http api
    网易云信
    QQ通讯
    
    详细对比:https://blog.csdn.net/weixin_33739646/article/details/
    
    每天发信息不过 10000 条
    
    大部分场景下自研成本比使用第三方的高
    
    自研的优势:可控
    

    1.3 即时通讯开源项目

    C++: teamtalk
    Go:GoBelieve goim
    Java:openfire

    2.1 即时通讯的基本架构

    在这里插入图片描述

    客户端与服务器端进行网络通信、收发消息
    
    连接层为客户端收发消息提供出入口。主
    要的任务:保持海量用户连接;解析协议,
    对传输内容进行编码;维护session;推送
    消息。
    核心业务层负责IM系统各项功能的核心逻
    辑实现。
    
    数据层负责IM系统相关数据的持久化存储,
    包括消息内容、账号信息等。
    

    2.2 IM技术的特点

    1. 实时性 :保证消息实时触达。(轮询与长连接)(消息提示推送,和我们阅读的消
      息是不一样的。)
    2. 可靠性 :保证消息的不丢失和不重复。(ACK 机制)
      TCP 只能保证消息数据链路可靠,不能保证业务可靠。
    3. 一致性 :保证同一条消息在多人、多终端展现顺序的一致性。(消息序号生成器)
    4. 安全性 :保证数据传输安全、数据存储安全、消息内容安全。(HTTPDNS 和TLS)

    3 即时通讯分层架构

    即时通讯系统常用分层架构
    接入层:entry/gate
    
    逻辑层:logic
    数据层:data
    
    路由层:route
    

    3.1 即时通讯分层架构-接入层

    在这里插入图片描述

    接入层的作用:
    ◼ 连接整流
    ◼ 通信安全
    ◼ 报文解压缩
    ◼ 初步防攻击
    

    3.1接入层-连接整流和通信安全

    在这里插入图片描述
    在这里插入图片描述

    3.1接入层-报文解压缩和初步防攻击

    在这里插入图片描述
    在这里插入图片描述

    3.2 即时通讯分层架构-逻辑层

    在这里插入图片描述

    1. 用户逻辑 :用户登录、用户退出、用户信息查询、用户更新签
    名、用户分组创建等
    2. 好友逻辑 :添加好友、删除好友、拉取好友列表、好友添加备
    注等
    3. 群组逻辑 :创建群、加入群、删除群、删除成员等
    4. 消息逻辑 :单聊文字消息、单聊语音消息、群聊文字消息、群
    聊语音消息、拉取离线消息等
    5. 其他 ,比如文件传输、图片传输等

    3.2 逻辑层设计核心-扩展性

    在这里插入图片描述

    1. 水平扩展各个逻辑模块
    2. 无缝添加新的逻辑服务,比如文件传输

    3.3 即时通讯分层架构-数据层

    在这里插入图片描述

    1. 对上游屏蔽存储引擎
    2. 对上游屏蔽cache层
    3. 对上游提供友好接口

    3.3.1 数据层-屏蔽存储引擎

    在这里插入图片描述在这里插入图片描述

    3.3.2 数据层-屏蔽cache层

    在这里插入图片描述

    3.3.3 数据层-提供友好接口

    在这里插入图片描述

    3.3.4 数据层-扩展性

    在这里插入图片描述

    3.4 即时通讯分层架构-路由层

    在这里插入图片描述

    1. 路由消息:消息投递
    2. 内存存储:用户临时数据,比如用户
      状态信息(在线/离线)

    3.4. 1 路由层-路由消息

    在这里插入图片描述

    4 Teamtalk

    为什么学习Teamtalk:
    ◼ CloudTalk 基于Teamtalk进行二次开发
    ◼ xx公司基于Teamtalk进行二次开发
    

    在这里插入图片描述

    5 即时通讯项目

    1. Android/iOS/PC:各种客户端。
    2. LoginServer: 主要负责负载均衡的作用,当收到客户端的请求时,分配一个负载最小的
      MsgServer给客户端。
    3. MsgServer: TT的主要服务端,负责维护各个客户端的链接,消息转发等功能。
    4. RouteServer:负责消息路由的功能,当msg_server发现某个用户不在本服务器内,而又有消
      息需要发给他,就会将消息转发给route_server,route_server会将消息发给相应的
      msg_server,由此可知,route_server也维护了一定的用户状态。
    5. DBProxy:在TT中负责了主要的业务逻辑,主要与存储层打交道,提供mysql以及redis的访问
      服务,屏蔽其他服务器与mysql与redis的直接交互。
    6. FileServer:文件服务器,提供客户端之间得文件传输服务,支持在线以及离线文件传输
    7. MsfsServer:图片存储服务器,提供头像,图片传输中的图片存储服务。
    8. PushServer:负责Android、IOS客户端提醒消息的推送,类似微信的锁屏提醒消息。
    9. Webserver:简单的管理功能。

    6.1 我们能从中学到什么

    1. 基础组件封装:thread、ringfifo等
    2. Epoll网络库封装(客户端服务端)
    3. HTTP模块封装
    4. HTTP api实战
    5. HTTPs
    6. Wesocket
    7. protobuf实战
    8. json
    9. MySQL连接池
      10.Redis连接池
      11.线程池
      12.数据库实战
      13.小文件存储系统原理
      14.音视频集成到即时通讯
      15.即时通讯技术的原理和实战
      1. 消息单聊(消息id)
      2. 消息群聊(分表的设计)
      3. 消息推送和拉取

    6.2 即时通讯重点

    实时性
     http
     socket
     websocket

    数据库
     数据库表设计
     分表设计
     密码存储方式
     最近会话表
     未读消息如何体现
     聊天消息分表问题

    单聊消息发送流程
     怎么保证数据的不丢失
     消息序号在哪里生成
     消息序号生成方式
     消息如何封装
     消息发送时的seq有什么作用
     消息发送后服务器怎么应答?
     接收端收到数据后如何应答
    
    客户端的单聊消息未读计数是怎么实现的
     服务器怎么保留消息未读计数
     客户端的未读消息计数从何而来
     客户端未读消息计数清 0 时向服务器发送了什么,服务器
    又是怎么清除未读消息计数
    
    文件传输原理
     文件传输分为在线传输离线传输
     在线传输和离线传输有什么区别
    群聊消息
     如何推送群聊
     群消息计数器
     群会话如何更新(每有一个人发送消
    息,则其他人都需要更新会话消息)
    群成员管理
     如何创建群
     如何删除群
     怎么使用redis管理群成员
    
    MySQL连接池设计
     为什么使用连接池
     连接池设置多大合适?
    
    redis连接池设计
     为什么使用连接池
     连接池设置多大合适?
    
    并发能力
     如何做到百万并发
     如何做到千万并发
    

    7.1 即时通讯项目部署

    1.保证redis正常运行;
    2.保证mysql正常运行;
    3.保证php正常运行;
    4.保证nginx正常运行;
    5.保证php正常运行,这里的php主要是web管理平台的使用;
    6.protobuf版本库目前server端是2.0的版本,Android_av使用了3.0的版
    本
    7.web服务器需要nginx支持;
    8.服务不启动的时候主要查看log是否正常。
    

    7.2 配置文件重点 1

    loginserver.conf负载均衡服务
    HttpPort:对应提供HTTP服务的端口,默认 8080
    MsgServerPort:msg服务器上报监听的端口,默认 8100
    
    msgserver.conf 消息服务
    ListenPort:连接msg服务器需要的端口
    LoginServerIP1:上报msg服务器负载的地址
    LoginServerPort1:上报msg服务器负载的端口
    RouteServerIP1:route服务器地址和端口
    RouteServerPort1:
    PushServerIP1:push推送服务器地址和端口
    PushServerPort1:
    FileServerIP1:文件传输服务器地址和端口
    IpAddr1:对外提供的往外ip,需要上报给login 服务器
    
    dbproxyserver.con 数据库中间件服务
    ListenPort:该服务监听的端口
    ThreadNum:线程池线程数量
    DBInstances=teamtalk_master,teamtalk_slave配置数据库实例
    
    #teamtalk_master
    teamtalk_master_host=127.0.0.1 数据库ip
    teamtalk_master_port=3306 数据库端口
    teamtalk_master_dbname=teamtalk 数据库名字
    teamtalk_master_username=root 用户名
    teamtalk_master_password=123456 密码
    teamtalk_master_maxconncnt=16 连接池最大连接数量
    
    #未读消息计数器的redis
    unread_host=127.0.0.1 redis地址
    unread_port=6379 redis端口
    unread_db=1 db索引
    unread_maxconncnt=16 连接池最大连接数量
    

    routeserver.conf 路由服务
    ListenIP=0.0.0.0 该服务监听ip
    ListenMsgPort=8200 该服务监听端口

    7.2 配置文件重点 2

    fileserver.conf文件传输服务
    ClientListenIP=0.0.0.0 该服务监听的地址
    ClientListenPort=8600 该服务监听的端口,
    供msg server连接

    httpmsgserver.conf HTTP reset api服务
    ListenPort=8400 该服务监听
    ConcurrentDBConnCnt=4 db_proxy服务连接通道数量
    DBServerIP1=127.0.0.1 db_proxy服务地址
    DBServerPort1=10600
    DBServerIP2=127.0.0.1
    DBServerPort2=10600
    
    RouteServerIP1=localhost route路由服务地址
    RouteServerPort1=8200
    
    msfs.conf 文件存储服务
    ListenIP=0.0.0.0 #可以监听多个IP,用;分割
    ListenPort=8700 该服务端口
    BaseDir=./tmp 存储地址
    FileCnt=0 最大文件数量
    FilesPerDir=30000 每个目录最大存储文件
    GetThreadCount=32 下载线程
    PostThreadCount=1 上传线程
    pushserver.conf 推送服务
    ListenIP=127.0.0.1
    ListenPort=8500 该服务监听端口
    
    CertPath=apns-dev-cert.pem
    KeyPath=apns-dev-key.pem
    KeyPassword=tt@mogujie
    
    #SandBox
    #1: sandbox 0: production
    SandBox=0
    

    8 通信协议解析

    在这里插入图片描述

    展开全文
  • Web即时通讯技术原理详解 前言 在web端的IM即时通讯应用,由于浏览器的兼容性以及其固有的“客户端请求服务器处理并响应”的C/S通信模型,造成了要在浏览器中实现一个兼容性较好的IM应用,其通信过程必然是诸多...

    Web端即时通讯技术原理详解

    前言

    在web端的IM即时通讯应用,由于浏览器的兼容性以及其固有的“客户端请求服务器处理并响应”的C/S通信模型,造成了要在浏览器中实现一个兼容性较好的IM应用,其通信过程必然是诸多技术的组合,本文的目的就是要详细探讨这些技术并分析其原理和过程。

    更多资料:

    Web端即时通讯技术盘点:

    Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

    Comet技术:

    Comet技术详解:基于HTTP长连接的Web端实时通信技术

    WEB端即时通讯:HTTP长连接、长轮询(long polling)详解

    WEB端即时通讯:不用WebSocket也一样能搞定消息的即时性

    开源Comet服务器iComet:支持百万并发的Web端即时通讯方案

    WebSocket的详细介绍:

    WebSocket详解(一):初步认识WebSocket技术

    WebSocket详解(二):技术原理、代码演示和应用案例

    WebSocket详解(三):深入WebSocket通信协议细节

    WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

    WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)

    WebSocket详解(六):刨根问底WebSocket与Socket的关系

    WebSocket从入门到精通,半小时就够!

    理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性

    八问WebSocket协议:为你快速解答WebSocket热门疑问

    Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架

    socket.io和websocket 之间是什么关系?有什么区别?

    Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?

    有关SSE的详细介绍文章请参见:

    SSE技术详解:一种全新的HTML5服务器推送事件技术

    一、传统Web的通信原理

    浏览器本身作为一个瘦客户端,不具备直接通过系统调用来达到和处于异地的另外一个客户端浏览器通信的功能。这和我们桌面应用的工作方式是不同的,通常桌面应用通过socket可以和远程主机上另外一端的一个进程建立TCP连接,从而达到全双工的即时通信。浏览器从诞生开始一直走的是客户端请求服务器,服务器返回结果的模式,所以要想实现两个客户端的通信,必然要通过服务器进行信息的转发
    在这里插入图片描述

    二、传统通信方式实现IM应用需要解决的问题

    1. 双全工通信:

      即浏览器拉取(pull)服务器数据,服务器推送(push)数据到浏览器;

    2. 低延迟:

      即浏览器A发送给B的信息经过服务器要快速转发给B,同理B的信息也要快速交给A,实际上就是要求任何浏览器能够快速请求服务器的数据,服务器能够快速推送数据到浏览器;

    3. 支持跨域:

      通常客户端浏览器和服务器都是处于网络的不同位置,浏览器本身不允许通过脚本直接访问不同域名下的服务器,即使IP地址相同域名不同也不行,域名相同端口不同也不行,这方面主要是为了安全考虑。

    三、全双工低延迟的解决办法

    1. 客户端浏览器轮询服务器(polling)

    其原理是在客户端通过Ajax的方式的方式每隔一小段时间就发送一个请求到服务器,服务器返回最新数据,然后客户端根据获得的数据来更新界面,这样就间接实现了即时通信。优点是简单,缺点是对服务器压力较大,浪费带宽流量(通常情况下数据都是没有发生改变的)。

    客户端代码如下:

    function createXHR(){
            if(typeof XMLHttpRequest !='undefined'){
                return new XMLHttpRequest();
            }else if(typeof ActiveXObject !='undefined' ){
                if(typeof arguments.callee.activeXString!="string"){
                    var versions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0",
                            "MSXML2.XMLHttp"],
                            i,len;
                    for(i=0,len=versions.length;i<len;i++){
                        try{
                            new ActiveXObject(versions[i]);
                            arguments.callee.activeXString=versions[i];
                            break;
                        }catch(ex) {
    
                        }
                    }
                }
            return new ActiveXObject(arguments.callee.activeXString);
           }else{
                throw new Error("no xhr object available");
            }
    }
    function polling(url,method,data){
        method=method ||'get';
        data=data || null;
        var xhr=createXHR();
        xhr.onreadystatechange=function(){
            if(xhr.readyState==4){
                if(xhr.status>=200&&xhr.status<300||xhr.status==304){
                    console.log(xhr.responseText);
                }else{
                    console.log("fail");
                }
            }
        };
        xhr.open(method,url,true);
        xhr.send(data);
    }
    setInterval(function(){
        polling('http://localhost:8088/time','get');
    },2000);
    

    每2秒就请求服务器一次获取服务器时间并打印出来。

    服务端代码(Node.js):

    var http=require('http');
    var fs = require("fs");
    var server=http.createServer(function(req,res){
    if(req.url=='/time'){
        //res.writeHead(200, {'Content-Type': 'text/plain','Access-Control-Allow-Origin':'http://localhost'});
        res.end(new Date().toLocaleString());
    };
    if(req.url=='/'){
        fs.readFile("./pollingClient.html", "binary", function(err, file) {
            if (!err) {
                res.writeHead(200, {'Content-Type': 'text/html'});
                res.write(file, "binary");
                res.end();
            }
    });
    }
    }).listen(8088,'localhost');
    server.on('connection',function(socket){
        console.log("客户端连接已经建立");
    });
    server.on('close',function(){
        console.log('服务器被关闭');
    });
    

    结果如下:

    2. 长轮询(long-polling)

    在上面的轮询解决方案中,由于每次都要发送一个请求,服务端不管数据是否发生变化都发送数据,请求完成后连接关闭。这中间经过的很多通信是不必要的,于是又出现了长轮询(long-polling)方式。这种方式是客户端发送一个请求到服务器,服务器查看客户端请求的数据是否发生了变化(是否有最新数据),如果发生变化则立即响应返回,否则保持这个连接并定期检查最新数据,直到发生了数据更新或连接超时。同时客户端连接一旦断开,则再次发出请求,这样在相同时间内大大减少了客户端请求服务器的次数。

    (详细技术文章请参见《WEB端即时通讯:HTTP长连接、长轮询(long polling)详解》)

    客户端代码如下:

    function createXHR(){
        if(typeof XMLHttpRequest !='undefined'){
            return new XMLHttpRequest();
        }else if(typeof ActiveXObject !='undefined' ){
            if(typeof arguments.callee.activeXString!="string"){
                var versions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0",
                              "MSXML2.XMLHttp"],
                    i,len;
                for(i=0,len=versions.length;i<len;i++){
                    try{
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString=versions[i];
                        break;
                    }catch(ex) {
    
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        }else{
            throw new Error("no xhr object available");
        }
    }
    function longPolling(url,method,data){
        method=method ||'get';
        data=data || null;
        var xhr=createXHR();
        xhr.onreadystatechange=function(){
            if(xhr.readyState==4){
                if(xhr.status>=200&&xhr.status<300||xhr.status==304){
                    console.log(xhr.responseText);
                }else{
                    console.log("fail");
                }
                longPolling(url,method,data);
            }
        };
        xhr.open(method,url,true);
        xhr.send(data);
    }
    longPolling('http://localhost:8088/time','get');
    

    在XHR对象的readySate为4的时候,表示服务器已经返回数据,本次连接已断开,再次请求服务器建立连接。

    服务端代码:

    var http=require('http');
    var fs = require("fs");
    var server=http.createServer(function(req,res){
        if(req.url=='/time'){
            setInterval(function(){
                sendData(res);
            },20000);
        };
        if(req.url=='/'){
            fs.readFile("./lpc.html", "binary", function(err, file) {
                if (!err) {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    res.write(file, "binary");
                    res.end();
                }
            });
        }
    }).listen(8088,'localhost');
    //用随机数模拟数据是否变化
    function sendData(res){
        var randomNum=Math.floor(10*Math.random());
        console.log(randomNum);
        if(randomNum>=0&&randomNum<=5){
            res.end(new Date().toLocaleString());
        }
    }
    

    在服务端通过生成一个在1到9之间的随机数来模拟判断数据是否发生了变化,当随机数在0到5之间表示数据发生了变化,直接返回,否则保持连接,每隔2秒再检测。

    结果如下:
    在这里插入图片描述
    可以看到返回的时间是没有规律的,并且单位时间内返回的响应数相比polling方式较少。

    3. 基于http-stream通信

    原理是让客户端在一次请求中保持和服务端连接不断开,然后服务端源源不断传送数据给客户端,就好比数据流一样,并不是一次性将数据全部发给客户端。它与polling方式的区别在于整个通信过程客户端只发送一次请求,然后服务端保持与客户端的长连接,并利用这个连接在回送数据给客户端。这种方案有分为几种不同的数据流传输方式。

    基于XHR对象的streaming方式

    这种方式的思想是构造一个XHR对象,通过监听它的onreadystatechange事件,当它的readyState为3的时候,获取它的responseText然后进行处理,readyState为3表示数据传送中,整个通信过程还没有结束,所以它还在不断获取服务端发送过来的数据,直到readyState为4的时候才表示数据发送完毕,一次通信过程结束。在这个过程中,服务端传给客户端的数据是分多次以stream的形式发送给客户端,客户端也是通过stream形式来获取的,所以称作http-streaming数据流方式。

    客户端代码:

    function createStreamClient(url,progress,done){
        //received为接收到数据的计数器
        var xhr=new XMLHttpRequest(),received=0;
        xhr.open("get",url,true);
        xhr.onreadystatechange=function(){
            var result;
            if(xhr.readyState==3){
                //console.log(xhr.responseText);
                result=xhr.responseText.substring(received);
                received+=result.length;
                progress(result);
            }else if(xhr.readyState==4){
                done(xhr.responseText);
            }
        };
        xhr.send(null);
        return xhr;
    }
    var client=createStreamClient("http://localhost:8088/stream",function(data){
        console.log("Received:"+data);
    },function(data){
        console.log("Done,the last data is:"+data);
    })
    

    这里由于客户端收到的数据是分段发过来的,所以最好定义一个游标received,来获取最新数据而舍弃之前已经接收到的数据,通过这个游标每次将接收到的最新数据打印出来,并且在通信结束后打印出整个responseText。

    服务端代码:

    var http=require('http');
    var fs = require("fs");
    var count=0;
    var server=http.createServer(function(req,res){
        if(req.url=='/stream'){
            res.setHeader('content-type', 'multipart/octet-stream');
            var timer=setInterval(function(){
                sendRandomData(timer,res);
            },2000);
     
        };
        if(req.url=='/'){
            fs.readFile("./xhr-stream.html", "binary", function(err, file) {
                if (!err) {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    res.write(file, "binary");
                    res.end();
                }
            });
        }
    }).listen(8088,'localhost');
    function sendRandomData(timer,res){
        var randomNum=Math.floor(10000*Math.random());
        console.log(randomNum);
        if(count++==10){
            clearInterval(timer);
            res.end(randomNum.toString());
        }
            res.write(randomNum.toString());
    }
    

    服务端通过计数器count将数据分十次发送,每次生成一个小于10000的随机数发送给客户端让它进行处理。

    结果如下:
    在这里插入图片描述
    可以看到每次传过来的数据流都进行了处理,同时打印出了整个最终接收到的完整数据。这种方式间接实现了客户端请求,服务端及时推送数据给客户端。

    基于iframe的数据流

    由于低版本的IE不允许在XHR的readyState为3的时候获取其responseText属性,为了达到在IE上使用这个技术,又出现了基于iframe的数据流通信方式。具体来讲,就是在浏览器中动态载入一个iframe,让它的src属性指向请求的服务器的URL,实际上就是向服务器发送了一个http请求,然后在浏览器端创建一个处理数据的函数,在服务端通过iframe与浏览器的长连接定时输出数据给客户端,但是这个返回的数据并不是一般的数据,而是一个类似于<script type=\"text/javascript\">parent.process('"+randomNum.toString()+"')</script>脚本执行的方式,浏览器接收到这个数据就会将它解析成js代码并找到页面上指定的函数去执行,实际上是服务端间接使用自己的数据间接调用了客户端的代码,达到实时更新客户端的目的。

    客户端代码如下:

    function process(data){
        console.log(data);
    }
    var dataStream = function (url) {
        var ifr = document.createElement("iframe"),timer;
        ifr.src = url;
        document.body.appendChild(ifr);
    };
    dataStream('http://localhost:8088/htmlfile');
    

    客户端为了简单起见,定义对数据处理就是打印出来。

    服务端代码:

    var http=require('http');
    var fs = require("fs");
    var count=0;
    var server=http.createServer(function(req,res){
        if(req.url=='/htmlfile'){
            res.setHeader('content-type', 'text/html');
            var timer=setInterval(function(){
                sendRandomData(timer,res);
            },2000);
     
        };
        if(req.url=='/'){
            fs.readFile("./htmlfile-stream.html", "binary", function(err, file) {
                if (!err) {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    res.write(file, "binary");
                    res.end();
                }
            });
        }
    }).listen(8088,'localhost');
    function sendRandomData(timer,res){
        var randomNum=Math.floor(10000*Math.random());
        console.log(randomNum.toString());
        if(count++==10){
            clearInterval(timer);
            res.end("<script type=\"text/javascript\">parent.process('"+randomNum.toString()+"')</script>");
        }
        res.write("<script type=\"text/javascript\">parent.process('"+randomNum.toString()+"')</script>");
    }
    

    服务端定时发送随机数给客户端,并调用客户端process函数。

    在IE5中测试结果如下:
    新手入门贴:史上最全Web端即时通讯技术原理详解_4.jpg 可以看到实现在低版本IE中客户端到服务器的请求-推送的即时通信。

    4. 基于htmlfile的数据流通信

    又出现新问题了,在IE中,使用iframe请求服务端,服务端保持通信连接没有全部返回之前,浏览器title一直处于加载状态,并且底部也显示正在加载,这对于一个产品来讲用户体验是不好的,于是谷歌的天才们又想出了一中hack方式。就是在IE中,动态生成一个htmlfile对象,这个对象是ActiveX形式的com组件,它实际上就是一个在内存中实现的HTML文档,通过将生成的iframe添加到这个内存中的HTMLfile中,并利用iframe的数据流通信方式达到上面的效果。同时由于HTMLfile对象并不是直接添加到页面上的,所以并没有造成浏览器显示正在加载的现象。

    客户端:

    function connect_htmlfile(url, callback) {
        var transferDoc = new ActiveXObject("htmlfile");
        transferDoc.open();
        transferDoc.write(
            "<!DOCTYPE html><html><body><script  type=\"text/javascript\">" +
            "document.domain='" + document.domain + "';" +
            "<\/script><\/body><\/html>");
        transferDoc.close();
        var ifrDiv = transferDoc.createElement("div");
        transferDoc.body.appendChild(ifrDiv);
        ifrDiv.innerHTML = "<iframe src='" + url + "'><\/iframe>";
        transferDoc.callback=callback;
        setInterval( function () {}, 10000);
    }
    function prograss(data) {
        alert(data);
    }
    connect_htmlfile('http://localhost:8088/htmlfile',prograss);
    

    服务端传送给iframe的是这样子:

    <script type=\"text/javascript\">callback.process('"+randomNum.toString()+"')</script>
    

    这样就在iframe流的原有方式下避免了浏览器的加载状态。

    5. SSE(服务器推送事件(Server-sent Events)

    为了解决浏览器只能够单向传输数据到服务端,HTML5提供了一种新的技术叫做服务器推送事件SSE,它能够实现客户端请求服务端,然后服务端利用与客户端建立的这条通信连接push数据给客户端,客户端接收数据并处理的目的。从独立的角度看,SSE技术提供的是从服务器单向推送数据给浏览器的功能,但是配合浏览器主动请求,实际上就实现了客户端和服务器的双向通信。它的原理是在客户端构造一个eventSource对象,该对象具有readySate属性,分别表示如下:0:正在连接到服务器;1:打开了连接;2:关闭了连接。 同时eventSource对象会保持与服务器的长连接,断开后会自动重连,如果要强制连接可以调用它的close方法。它可以监听onmessage事件,服务端遵循SSE数据传输的格式给客户端,客户端在onmessage事件触发时就能够接收到数据,从而进行某种处理。

    (关于该技术详细介绍请参见《SSE技术详解:一种全新的HTML5服务器推送事件技术》)

    客户端:

    var source=new EventSource('http://localhost:8088/evt');
        source.addEventListener('message', function(e) {
            console.log(e.data);
        }, false);
        source.onopen=function(){
            console.log('connected');
        }
        source.onerror=function(err){
            console.log(err);
        }
    

    服务端:

    var http=require('http');
    var fs = require("fs");
    var count=0;
    var server=http.createServer(function(req,res){
        if(req.url=='/evt'){
            //res.setHeader('content-type', 'multipart/octet-stream');
            res.writeHead(200, {"Content-Type":"tex" +
                "t/event-stream", "Cache-Control":"no-cache",
                'Access-Control-Allow-Origin': '*',
                "Connection":"keep-alive"});
            var timer=setInterval(function(){
                if(++count==10){
                    clearInterval(timer);
                    res.end();
                }else{
                    res.write('id: ' + count + '\n');
                    res.write("data: " + new Date().toLocaleString() + '\n\n');
                }
            },2000);
        };
        if(req.url=='/'){
            fs.readFile("./sse.html", "binary", function(err, file) {
                if (!err) {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    res.write(file, "binary");
                    res.end();
                }
            });
        }
    }).listen(8088,'localhost');
    

    这里服务端发送的数据要遵循一定的格式,通常是id:(空格)数据(换行符)data:(空格)数据(两个换行符),如果不遵循这种格式,实际上客户端是会触发error事件的。这里的id是用来标识每次发送的数据的id,是强制要加的。

    结果如下:

    新手入门贴:史上最全Web端即时通讯技术原理详解_1.jpg

    四、跨域解决办法

    1. 基于XHR的COSR(跨域资源共享)

    CORS(跨域资源共享)是一种允许浏览器脚本向出于不同域名下服务器发送请求的技术,它是在原生XHR请求的基础上,XHR调用open方法时,地址指向一个跨域的地址,在服务端通过设置 'Access-Control-Allow-Origin':'*' 响应头告诉浏览器,发送的数据是一个来自于跨域的并且服务器允许响应的数据,浏览器接收到这个header之后就会绕过平常的跨域限制,从而与平时的XHR通信没有区别。该方法的主要好处是在于客户端代码不用修改,服务端只需要添加'Access-Control-Allow-Origin':'*'头部即可。适用于ff, safari, opera, chrome 等非IE浏览器。跨域的XHR相比非跨域的XHR有一些限制,这是为了安全所需要的,主要有以下限制: 客户端不能使用setRequestHeader设置自定义头部;不能发送和接收cookie;调用getAllResponseHeaders()方法总会返回空字符串。

    客户端代码:

    var polling=function(){
            var xhr=new XMLHttpRequest();
            xhr.onreadystatechange=function(){
                if(xhr.readyState==4)
                    if(xhr.status==200){
                        console.log(xhr.responseText);
                    }
                }
        xhr.open('get','http://localhost:8088/cors');
        xhr.send(null);
        };
        setInterval(function(){
            polling();
        },1000);
    

    服务端代码:

    var http=require('http');
    var fs = require("fs");
    var server=http.createServer(function(req,res){
        if(req.url=='/cors'){
                res.writeHead(200, {'Content-Type': 'text/plain','Access-Control-Allow-Origin':'http://localhost'});
                res.end(new Date().toString());
        }
        if(req.url=='/jsonp'){
     
        }
    }).listen(8088,'localhost');
    server.on('connection',function(socket){
        console.log("客户端连接已经建立");
    });
    server.on('close',function(){
        console.log('服务器被关闭');
    });
    

    注意服务端需要设置头部Access-Control-Allow-Origin为需要跨域的域名。

    这里为了测试在端口8088上监听请求,然后让客户端在80端口上请求服务,结果如下:
    在这里插入图片描述

    2. 基于XDR的CORS

    对于IE8-10,它是不支持使用原生的XHR对象请求跨域服务器的,它自己实现了一个XDomainRequest对象,类似于XHR对象,能够发送跨域请求,它主要有以下限制: cookie不会随请求发送,也不会随响应返回;只能设置请求头部信息中的Content-Type字段;不能访问响应头部信息;只支持Get和Post请求;只支持IE8-IE10。

    客户端请求代码:

    var polling=function(){
       var xdr=new XDomainRequest();
       xdr.onload=function(){
           console.log(xdr.responseText);
       };
       xdr.onerror=function(){
           console.log('failed');
       };
       xdr.open('get','http://localhost:8088/cors');
       xdr.send(null);
    };
    setInterval(function(){
       polling();
    },1000);
    

    服务端代码和同上

    在IE8中测试结果如下:
    在这里插入图片描述

    3. 基于JSONP的跨域

    这种方式不需要在服务端添加Access-Control-Allow-Origin头信息,其原理是利用HTML页面上script标签对跨域没有限制的特点,让它的src属性指向服务端请求的地址,其实是通过script标签发送了一个http请求,服务器接收到这个请求之后,返回的数据是自己的数据加上对客户端JS函数的调用,其原理类似于我们上面所说的iframe流的方式,客户端浏览器接收到返回的脚本调用会解析执行,从而达到更新界面的目的。

    客户端代码如下:

    function callback(data){
        console.log("获得的跨域数据为:"+data);
    }
    function sendJsonp(url){
        var oScript=document.createElement("script");
        oScript.src=url;
        oScript.setAttribute('type',"text/javascript");
        document.getElementsByTagName('head')[0].appendChild(oScript);
    }
    setInterval(function(){
        sendJsonp('http://localhost:8088/jsonp?cb=callback');
    },1000);
    

    服务端代码:

    var http=require('http');
    var url=require('url');
    var server=http.createServer(function(req,res){
        if(/\/jsonp/.test(req.url)){
            var urlData=url.parse(req.url,true);
            var methodName=urlData.query.cb;
            res.writeHead(200,{'Content-Type':'application/javascript'});
            //res.end("<script type=\"text/javascript\">"+methodName+"("+new Date().getTime()+");</script>");
            res.end(methodName+"("+new Date().getTime()+");");
            //res.end(new Date().toString());
        }
    }).listen(8088,'localhost');
    server.on('connection',function(socket){
        console.log("客户端连接已经建立");
    });
    server.on('close',function(){
        console.log('服务器被关闭');
    });
    

    注意这里服务端输出的数据content-type首部要设定为application/javascript,否则某些浏览器会将其当做文本解析。

    结果如下:

    新手入门贴:史上最全Web端即时通讯技术原理详解_9.png

    五、WebSocket

    在上面的这些解决方案中,都是利用浏览器单向请求服务器或者服务器单向推送数据到浏览器这些技术组合在一起而形成的hack技术,在HTML5中,为了加强web的功能,提供了websocket技术,它不仅是一种web通信方式,也是一种应用层协议。它提供了浏览器和服务器之间原生的双全工跨域通信,通过浏览器和服务器之间建立websocket连接(实际上是TCP连接),在同一时刻能够实现客户端到服务器和服务器到客户端的数据发送。

    首先是客户端new一个websocket对象,该对象会发送一个http请求到服务端,服务端发现这是个websocket请求,会同意协议转换,发送回客户端一个101状态码的response,以上过程称之为一次握手,经过这次握手之后,客户端就和服务端建立了一条TCP连接,在该连接上,服务端和客户端就可以进行双向通信了。这时的双向通信在应用层走的就是ws或者wss协议了,和http就没有关系了。

    关于ws协议要求的数据格式官网指定如下:
    在这里插入图片描述

    **FIN字段:**占用1位,表示这是一个数据帧的结束标志,同时也下一个数据帧的开始标志;

    **opcode字段:**占用4位,当为1时,表示传递的是text帧,2表示二进制数据帧,8表示需要结束此次通信(就是客户端或者服务端哪个发送给对方这个字段,就表示对方要关闭连接了)。9表示发送的是一个ping数据;

    **mask:**占用1位,为1表示masking-key字段可用;

    **masking-key字段:**用来对客户端发送来的数据做unmask操作的。它占用0到4个字节。

    **Payload字段:**表示实际发送的数据,可以是字符数据也可以是二进制数据。

    服务端代码:

    //握手成功之后就可以发送数据了
    var crypto = require('crypto');
    var WS = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
    var server=require('net').createServer(function (socket) {
        var key;
        socket.on('data', function (msg) {
            if (!key) {
                //获取发送过来的Sec-WebSocket-key首部
                key = msg.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
                key = crypto.createHash('sha1').update(key + WS).digest('base64');
                socket.write('HTTP/1.1 101 Switching Protocols\r\n');
                socket.write('Upgrade: WebSocket\r\n');
                socket.write('Connection: Upgrade\r\n');
                //将确认后的key发送回去
                socket.write('Sec-WebSocket-Accept: ' + key + '\r\n');
                //输出空行,结束Http头
                socket.write('\r\n');
            } else {
                var msg=decodeData(msg);
                console.log(msg);
                //如果客户端发送的操作码为8,表示断开连接,关闭TCP连接并退出应用程序
                if(msg.Opcode==8){
                    socket.end();
                    server.unref();
                }else{
                    socket.write(encodeData({FIN:1,
                        Opcode:1,
                        PayloadData:"接受到的数据为"+msg.PayloadData}));
                }
     
            }
        });
    });
        server.listen(8000,'localhost');
    //按照websocket数据帧格式提取数据
    function decodeData(e){
        var i=0,j,s,frame={
            //解析前两个字节的基本数据
            FIN:e[i]>>7,Opcode:e[i++]&15,Mask:e[i]>>7,
            PayloadLength:e[i++]&0x7F
        };
        //处理特殊长度126和127
        if(frame.PayloadLength==126)
            frame.length=(e[i++]<<8)+e[i++];
        if(frame.PayloadLength==127)
            i+=4, //长度一般用四字节的整型,前四个字节通常为长整形留空的
                frame.length=(e[i++]<<24)+(e[i++]<<16)+(e[i++]<<8)+e[i++];
        //判断是否使用掩码
        if(frame.Mask){
            //获取掩码实体
            frame.MaskingKey=[e[i++],e[i++],e[i++],e[i++]];
            //对数据和掩码做异或运算
            for(j=0,s=[];j<frame.PayloadLength;j++)
                s.push(e[i+j]^frame.MaskingKey[j%4]);
        }else s=e.slice(i,frame.PayloadLength); //否则直接使用数据
        //数组转换成缓冲区来使用
        s=new Buffer(s);
        //如果有必要则把缓冲区转换成字符串来使用
        if(frame.Opcode==1)s=s.toString();
        //设置上数据部分
        frame.PayloadData=s;
        //返回数据帧
        return frame;
    }
    //对发送数据进行编码
    function encodeData(e){
        var s=[],o=new Buffer(e.PayloadData),l=o.length;
        //输入第一个字节
        s.push((e.FIN<<7)+e.Opcode);
        //输入第二个字节,判断它的长度并放入相应的后续长度消息
        //永远不使用掩码
        if(l<126)s.push(l);
        else if(l<0x10000)s.push(126,(l&0xFF00)>>2,l&0xFF);
        else s.push(
                127, 0,0,0,0, //8字节数据,前4字节一般没用留空
                    (l&0xFF000000)>>6,(l&0xFF0000)>>4,(l&0xFF00)>>2,l&0xFF
            );
        //返回头部分和数据部分的合并缓冲区
        return Buffer.concat([new Buffer(s),o]);
    }
    

    服务端通过监听data事件来获取客户端发送来的数据,如果是握手请求,则发送http 101响应,否则解析得到的数据并打印出来,然后判断是不是断开连接的请求(Opcode为8),如果是则断开连接,否则将接收到的数据组装成帧再发送给客户端。

    客户端代码:

    window.onload=function(){
        var ws=new WebSocket("ws://127.0.0.1:8088");
        var oText=document.getElementById('message');
        var oSend=document.getElementById('send');
        var oClose=document.getElementById('close');
        var oUl=document.getElementsByTagName('ul')[0];
        ws.onopen=function(){
            oSend.onclick=function(){
                if(!/^\s*$/.test(oText.value)){
                    ws.send(oText.value);
                }
            };
    
        };
        ws.onmessage=function(msg){
            var str="<li>"+msg.data+"</li>";
            oUl.innerHTML+=str;
        };
        ws.onclose=function(e){
            console.log("已断开与服务器的连接");
            ws.close();
        }
    }
    

    客户端创建一个websocket对象,在onopen时间触发之后(握手成功后),给页面上的button指定一个事件,用来发送页面input当中的信息,服务端接收到信息打印出来,并组装成帧返回给日客户端,客户端再append到页面上。

    客户结果如下:
    新手入门贴:史上最全Web端即时通讯技术原理详解_4.jpg
    服务端输出结果:
    新手入门贴:史上最全Web端即时通讯技术原理详解_5.jpg
    从上面可以看出,WebSocket在支持它的浏览器上确实提供了一种全双工跨域的通信方案,所以在各以上各种方案中,我们的首选无疑是WebSocket。

    结束语

    上面论述了这么多对于IM应用开发所涉及到的通信方式,在实际开发中,我们通常使用的是一些别人写好的实时通讯的库,比如socket.iosockjs,他们的原理就是将上面(还有一些其他的如基于Flash的push)的一些技术进行了在客户端和服务端的封装,然后给开发者一个统一调用的接口。这个接口在支持websocket的环境下使用websocket,在不支持它的时候启用上面所讲的一些hack技术。

    从实际来讲,单独使用本文上述所讲的任何一种技术(WebSocket除外)达不到我们在文章开头提出的低延时,双全工、跨域的全部要求,只有把他们组合起来才能够很好地工作,所以通常情况下,这些库都是在不同的浏览器上采用各种不同的组合来实现实时通讯的。

    下面是sockjs在不同浏览器下面采取的不同组合方式:
    在这里插入图片描述

    全站即时通讯技术资料分类

    [1] 网络编程基础资料:

    TCP/IP详解 - 第11章·UDP:用户数据报协议

    TCP/IP详解 - 第17章·TCP:传输控制协议

    TCP/IP详解 - 第18章·TCP连接的建立与终止

    TCP/IP详解 - 第21章·TCP的超时与重传

    理论经典:TCP协议的3次握手与4次挥手过程详解

    理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程

    计算机网络通讯协议关系图(中文珍藏版)

    NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等

    UDP中一个包的大小最大能多大?

    Java新一代网络编程模型AIO原理及Linux系统AIO介绍

    NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战

    NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战

    更多同类文章 ……

    [2] 有关IM/推送的通信格式、协议的选择:

    为什么QQ用的是UDP协议而不是TCP协议?

    移动端即时通讯协议选择:UDP还是TCP?

    如何选择即时通讯应用的数据传输格式

    强列建议将Protobuf作为你的即时通讯应用数据传输格式

    移动端IM开发需要面对的技术问题(含通信协议选择)

    简述移动端IM开发的那些坑:架构设计、通信协议和客户端

    理论联系实际:一套典型的IM通信协议设计详解

    58到家实时消息系统的协议设计等技术实践分享

    更多同类文章 ……

    [3] 有关IM/推送的心跳保活处理:

    Android进程保活详解:一篇文章解决你的所有疑问

    Android端消息推送总结:实现原理、心跳保活、遇到的问题等

    为何基于TCP协议的移动端IM仍然需要心跳保活机制?

    微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)

    微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)

    移动端IM实践:实现Android版微信的智能心跳机制

    移动端IM实践:WhatsApp、Line、微信的心跳策略分析

    更多同类文章 ……

    [4] 有关WEB端即时通讯开发:

    新手入门贴:史上最全Web端即时通讯技术原理详解

    Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

    SSE技术详解:一种全新的HTML5服务器推送事件技术

    Comet技术详解:基于HTTP长连接的Web端实时通信技术

    WebSocket详解(一):初步认识WebSocket技术

    socket.io实现消息推送的一点实践及思路更多同类文章 ……

    [5] 有关IM架构设计:

    浅谈IM系统的架构设计

    简述移动端IM开发的那些坑:架构设计、通信协议和客户端

    一套原创分布式即时通讯(IM)系统理论架构方案

    从零到卓越:京东客服即时通讯系统的技术架构演进历程

    蘑菇街即时通讯/IM服务器开发之架构选择

    腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT

    微信技术总监谈架构:微信之道——大道至简(演讲全文)

    如何解读《微信技术总监谈架构:微信之道——大道至简》

    快速裂变:见证微信强大后台架构从0到1的演进历程(一)

    17年的实践:腾讯海量产品的技术方法论

    更多同类文章 ……

    [6] 有关IM安全的文章:

    即时通讯安全篇(一):正确地理解和使用Android端加密算法

    即时通讯安全篇(二):探讨组合加密算法在IM中的应用

    即时通讯安全篇(三):常用加解密算法与通讯安全讲解

    即时通讯安全篇(四):实例分析Android中密钥硬编码的风险

    传输层安全协议SSL/TLS的Java平台实现简介和Demo演示

    理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)

    微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解

    来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享

    更多同类文章 ……

    [7] 有关实时音视频开发:

    即时通讯音视频开发(一):视频编解码之理论概述

    即时通讯音视频开发(二):视频编解码之数字视频介绍

    即时通讯音视频开发(三):视频编解码之编码基础

    即时通讯音视频开发(四):视频编解码之预测技术介绍

    即时通讯音视频开发(五):认识主流视频编码技术H.264

    即时通讯音视频开发(六):如何开始音频编解码技术的学习

    即时通讯音视频开发(七):音频基础及编码原理入门

    即时通讯音视频开发(八):常见的实时语音通讯编码标准

    即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述

    即时通讯音视频开发(十):实时语音通讯的回音消除技术详解

    即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解

    即时通讯音视频开发(十二):多人实时音视频聊天架构探讨

    即时通讯音视频开发(十三):实时视频编码H.264的特点与优势

    即时通讯音视频开发(十四):实时音视频数据传输协议介绍

    即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况

    即时通讯音视频开发(十六):移动端实时音视频开发的几个建议

    即时通讯音视频开发(十七):视频编码H.264、V8的前世今生

    简述开源实时音视频技术WebRTC的优缺点

    良心分享:WebRTC 零基础开发者教程(中文)

    更多同类文章 ……

    [8] IM开发综合文章:

    移动端IM开发需要面对的技术问题

    开发IM是自己设计协议用字节流好还是字符流好?

    请问有人知道语音留言聊天的主流实现方式吗?

    IM系统中如何保证消息的可靠投递(即QoS机制)

    谈谈移动端 IM 开发中登录请求的优化

    完全自已开发的IM该如何设计“失败重试”机制?

    微信对网络影响的技术试验及分析(论文全文)

    即时通讯系统的原理、技术和应用(技术论文)

    开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀

    更多同类文章 ……

    [9] 开源移动端IM技术框架资料:

    开源移动端IM技术框架MobileIMSDK:快速入门

    开源移动端IM技术框架MobileIMSDK:常见问题解答

    开源移动端IM技术框架MobileIMSDK:压力测试报告

    开源移动端IM技术框架MobileIMSDK:Android版Demo使用帮助

    开源移动端IM技术框架MobileIMSDK:Java版Demo使用帮助

    开源移动端IM技术框架MobileIMSDK:iOS版Demo使用帮助

    开源移动端IM技术框架MobileIMSDK:Android客户端开发指南

    开源移动端IM技术框架MobileIMSDK:Java客户端开发指南

    开源移动端IM技术框架MobileIMSDK:iOS客户端开发指南

    开源移动端IM技术框架MobileIMSDK:Server端开发指南

    更多同类文章 ……

    [10] 有关推送技术的文章:

    iOS的推送服务APNs详解:设计思路、技术原理及缺陷等

    Android端消息推送总结:实现原理、心跳保活、遇到的问题等

    扫盲贴:认识MQTT通信协议

    一个基于MQTT通信协议的完整Android推送Demo

    求教android消息推送:GCM、XMPP、MQTT三种方案的优劣

    移动端实时消息推送技术浅析

    扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别

    绝对干货:基于Netty实现海量接入的推送服务技术要点

    移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)

    为何微信、QQ这样的IM工具不使用GCM服务推送消息?

    更多同类文章 ……

    [11] 更多即时通讯技术好文分类:

    http://www.52im.net/forum.php?mod=collection&op=all

    (原文链接:http://www.cnblogs.com/myzhibie/p/4589420.html)

    展开全文
  • 用java的ssh框架写出一套即时通讯web应用 基本也有朋友圈的小功能,而android端就是这个,2014年练习作品 此app是基于现即时通讯软件流行的xmpp协议 xmpp+asmack+openfire 服务器在web端开放了9090以供web后台使用 #接...
  • **即时通讯(IM)**是RDIFramework.NET敏捷开发框架全新提供的一个基于Web即时通讯、内部聊天沟通的工具。界面美观大方对于框架内部进行消息的沟通非常方便。基于RDIFramework.NET敏捷开发框架即时通讯IM支持...
  • android socket 即时通讯开发
  • E2EE+VUE+WS+miniBlink 实现即时通讯聊天客户Duan 开发所需环境:易语言 、E2EE、VUE、miniBlink框架 已集成成品和所有源代码 动态GIF演示:
  • 即时通讯

    2021-02-10 21:01:16
    Laravel是一个具有表达力,优雅语法的Web应用程序框架。 我们认为,发展必须是一种令人愉悦的创造力,才能真正实现。 Laravel通过减轻许多Web项目中使用的常见任务来减轻开发工作的痛苦,例如: 。 。 用于和存储...
  • 企业内部使用的一个即时通讯工具,实现了即时通讯,发送文件,群组通讯等常用功能 .软件包含了三部分,客户端,服务器端,一个辅助的发送文件的WEB应用,最新版本界面参考了 PC端的微信。 功能介绍 该源码主要功能...
  • websocket服务采用的国内知名的第三方websocket框架【GoEasy】实现。 源代码精炼,层次清晰,非常适合有学习、开发websocket聊天软件的开发者。 运行步骤: 1、获取GoEasy Appkey 先到GoEasy官网注册一个账号,登录后...
  • 兼容所有浏览器 适合Linux xp服务器。源码共享兼容所有浏览器 适合Linux xp服务器。源码共享兼容所有浏览器 适合Linux xp服务器。源码共享兼容所有浏览器 适合Linux xp服务器。源码共享
  • 使用SSM框架整合websocket实现即时通讯功能,可以实现私聊和群聊,里面附带mysql数据库脚本
  • springboot框架下利用websocket实现即时通讯(文章末尾有git项目打包文件,直接下载使用即可) 用websocket实现简单的在线聊天,先画个时序图,直观感受下流程 SystemController类 import org.springframework.web....
  • WEB即时通讯/消息推送

    万次阅读 多人点赞 2017-03-09 22:12:04
    通常进行的Web开发都是由客户端主动发起的请求,然后服务器对请求做出响应并返回给客户端。但是在很多情况下,你也许会希望由服务器主动对客户端发送一些数据。 那么,该如何实现这个需求,或者说该如何向网页推送...
  • 这个感悟是我的两个经历得出的感悟: 1)我曾经做过产品经理,参与到了一个平台性的产品开发,初期这个产品是团队自研的,功能本身不全面,后来用户越来越多,im这块问题也原来越多,而且影响到了整个web端和移动...
  • 有关Web即时通讯技术的文章我已整理过很多篇,阅读过的读者可能都很熟悉,早期的Web即时通讯方案,受限于Web客户端的技术限制,想实现真正的“即时”通信,难度相当大。 传统的Web即时通讯技术从短轮询到长...
  • 基于springBoot框架即时通讯app,同时使用了其他的一些框架,是一个初学者学习相关内容的基础好项目,注释比较清晰。对应blog:https://blog.csdn.net/weixin_44702572/article/details/106919517
  • IM即时通讯软件源码是一个完整的消息传递套件,供企业构建跨 Web、Android、iOS 设备的可定制协作平台,以建立虚拟连接。Instant Messaging 解决方案提供多种通信媒介,如语音和视频通话、实时聊天、视频会议,以...
  • 基于mina或netty框架下的推送系统,或许有一些企业有着自己一套即时通讯系统的需求,那么CIM为您提供了一个解决方案,目前CIM支持websocket,android,ios,桌面应用,系统应用等多端接入支持,可应用于移动应用,...
  • OpenIM:由前微信技术专家打造的基于 Go 实现的即时通讯(IM)开源项目,包括IM服务端和客户端SDK。开发者私有化部署,基于SDK二次开发,可以轻松替代第三方IM云服务,打造具备聊天、社交功能的app。无论是开发同城...
  • 该项目是一套基于mina或netty框架下的推送系统,或许有一些企业有着自己一套即时通讯系统的需求,那么CIM为您提供了一个解决方案,目前CIM支持websocket,android,ios,桌面应用,系统应用等多端接入支持,可应用于...
  • java即时通讯聊天工具

    2022-03-28 12:58:57
    摘要:即时通讯(Instant Messaging)是目前Internet上最为流行的通讯方式,各种各样的即时通讯软件也层出不穷;服务提供商也提供了越来越丰富的通讯服务功能。Java是当前比较流行的开发语言之一,它有着自己的易用...
  • 1/ 概述利用Spring Boot作为基础框架,Spring Security作为安全框架,WebSocket作为通信框架,实现点对点聊天和群聊天。2/ 所需依赖Spring Boot 版本 1.5.3,使用MongoDB存储数据(非必须),Maven依赖如下:1.83.0.0....
  • im即时通讯开源

    2021-02-28 19:15:15
    激发最好的开源现在最好的即时通讯软件是开源的即时通讯开源项目。当然,最近在GitHub上比较的Startalk啊,我最近重新选择了模型,程序员兄弟找到了这个好资源。 它似乎采用了一种比较流行的分散设计,开源代码也...
  • .net 网页即时通讯,包括前端即时通讯框架,包括websocket服务端。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,407
精华内容 5,762
关键字:

web即时通讯框架