zoukankan      html  css  js  c++  java
  • XMPP 和 OpenFire

    XMPP

    XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。是一种数据传输协议。
    XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。

    XMPP 地址格式

    一个XMPP节点的唯一标示符jabber identifier(JID),即实体地址,用来表示一个Jabber用户,但是也可以表示其他内容,例如一个聊天室.

    一个有效的JID包括一系列元素:

    • (1)域名(domain identifier);
    • (2)节点(node identifier);
    • (3)源(resource identifier).

    它的格式是 node@domain/resource,node@domain,类似电子邮件的地址格式.

    • domain用来表示接点不同的设备或位置,这个是可选的,例如a在Server1上注册了一个用户,用户名为doom,那么a的JID就是 doom@serverl,在发送消息时,指明 doom@serverl 就可以了,
    • resource可以不用指定,但a在登录到这个Server时,fl的JID可能是 doom@serverl/exodus (如果a用Exodus软件登录),也可能是 doom@serverl/psi (如果a用psi软件登录).资源只用来识别属于用户的位置或设备等,一个用户可以同时以多种资源与同一个XMPP服务器连接。

    XMPP 协议的 XML 格式:

    image

    这里有三个顶级 XML 元素: Presence、Message、IQ,每个的含义如下:

    <Presence> 用来表明用户的状态,

    如:online、away、dnd(请勿打扰)等。当用户离线或改变自己的状态时,就会在stream的上下文中插入一个Presence元素,来表明自身的状态.

    <Message> 用于在两个jabber用户之间发送信息。

    Jsm(jabber会话管理器)负责满足所有的消息,不管目标用户的状态如何。如果用户在线jsm立即提交;否则jsm就存储。

    To :标识消息的接收方。
    from : 指发送方的名字或标示(id)o
    Text: 此元素包含了要提交给目标用户的信息。

    < IQ > 一种请求/响应机制,

    从一个节点从发送请求,另外一个节点接受请求,并进行响应.
    例如,client在stream的上下文中插入一个元素,向Server请求得到自己的好友列表,Server返回一个,里面是请求的结果.

    <iq > 主要的属性是type。包括:
    Get :获取当前域值。
    Set :设置或替换get查询的值。
    Result :说明成功的响应了先前的查询。
    Error: 查询和响应中出现的错误。

    XML流


    XMPP本质上是一种XML流技术。

    客户端开始和XMPP服务器会话,会打开一个长时间的TCP连接,然后和服务器协商一个流。
    一旦你和你的服务器建立了一个XML流,你和你的服务器可以通过流交换三个特殊的XML片段:<message/>,<presence/>,<iq/>.这些片段称为XML节。而且一旦你已建立一个XML流,你可以通过流发送无数个节。

    下图是 C 客户端  S 服务器端 XML流的精简内容:

    C:  <stream:stream>
    C:  <presence/>
    C:  <iq type="get">
               <query xmlns="jabber:iq:roster"/>
        </iq>
    S:  <iq type="result">
               <query xmlns="jabber:iq:roster">
                <item jid="suke@skh.whu.edu.cn"xs/>
                <item jid="gmz@skh.whu.edu.cn"/>
                <item jid="beta@skh.whu.edu.cn"/>
            </query>
        </iq>
    C:  <message from="suke@skh.whu.edu.cn" 
                  to="beta@skh.whu.edu.cn">
               <body>Off with his head!</body>
        </message>
    S:  <message from="lj@skh.whu.edu.cn"
                  to="cyl@skh.whu.edu.cn ">
               <body>You are all pardoned.</body>
        </message>
    C:  <presence type="unavailable"/>
    C:     </stream:stream>

    XMPP面临的问题:

      • XMPP是基于稳定长连接网络环境所设计的,对于不够稳定和带宽小的移动网络不是非常合适。
      • 由于XMPP基于XML,所以流量大,流量问题对于移动网络来说非常敏感,然后就是消息不可靠、CMWAP兼容、开源项目对协议实现不完善等问题,也是XMPP面临的问题。

    数据负载太重:随着通常超过 70%的 XMPP 协议的服务器的数据流量的存在和近60%的被重复转发,XMPP 协议目前拥有一个大型架空中存在的数据提供给多个收件人。新的议定书正在研究,以减轻这一问题。

    没有二进制数据:XMPP 协议的方式被编码为一个单一的长的 XML 文件,因此无法提供修改二进制数据。因此, 文件传输协议一样使用外部的 HTTP。如果不可避免,XMPP 协议还提供了带编码的文件传输的所有数据使用的 Base64。至于其他二进制数据加密会话(encrypted conversations)或图形图标(graphic icons)以嵌入式使用相同的方法。

    XMPP 优化的一个方案是:

    • XML通过精简压缩来实现流量可控。
    • 消息的不可靠可以通过扩展XMPP来实现ACK

    OpenFire

    Openfire是XMPP领域最知名的开源项目,它简单易用,是很多团队的首选方案,这是国内使用最多的开源方案。Openfire虽然优点很多,但是缺点也不少,最致命的就是它的分布式扩展能力很弱,当用户量很大的时候,水平扩展就成为它的瓶颈所在。

    消息握手

    经常会有人发现,Openfire的两个客户端,在网络不稳定的情况下,会丢失消息。起初我也不知道到底发生了什么,直到后来,在测试中发现,当你用连接上通讯服务器后,直接拔了路由器,wifi异常断开,客户端与Server没办法握手告知TCP断线的事情,所以你会在一段时间内,服务器认为你在线,而实际你离线。这种情况在地铁、快速移动切换网络基站的情况下也经常有复现。此时Openfire收到关于你的消息会直接推送给你,而你此时又因为没有网络收取不到,所以消息丢失。

    解决办法:消息进行握手,每条消息发给客户端,都需要客户端回复回执,否则一直保存在服务器。

    心跳机制

    因为上述问题,所以就要经常清理那些失效客户端,保证客户端和服务器状态同步。

    如每15s - 60s 客户端定时发送一个小型的msg给服务器,服务器收到后回复一个callback。

    如果服务器120s内没有收取到任何消息,那么close Session。

    虽然XMPP有很多弊端,但是它的生态目前是最完善的,如果从成本角度来考量,XMPP是前期投入最小产出最快的。但是如果是搭建一个SAAS平台或者千万量级的IM,XMPP就不是最优的选择了。

    参考资料:

    漫谈IM通信架构
    http://www.yangguo.info/2015/08/17/%E6%BC%AB%E8%B0%88%E9%80%9A%E8%AE%AF%E6%9E%B6%E6%9E%84/ 

    开源移动通讯架构与XMPP
    http://timyang.net/im/mobile-im-xmpp/ 

    xmpp协议详解一:xmpp基本概念
    http://www.jianshu.com/p/a94749385755 

    即时通讯协议的选型之XMPP
    http://www.biaodianfu.com/xmpp.html 

    XMPP 协议适合用来做移动 IM 么?
    https://segmentfault.com/a/1190000000656509 

    http://www.mikewootc.com/wiki/net/protocol/xmpp.html

  • 相关阅读:
    .net Dapper 学习系列(1) ---Dapper入门
    ASP.NET WebApi 学习与实践系列(2)---WebApi 路由请求的理解
    ASP.NET WebApi 学习与实践系列(1)---如何创建 WebApi
    Sqlserver 总结(2) 存储过程
    Image.Save出错 GDI 一般错误
    python导入模块的两种方式
    从1KW条数据中筛选出1W条最大的数
    C# EF更新当前实体报错 ObjectManager无法管理具有相同键值的多个对象
    微信小程序 异步请求拿数据+使用外部js库
    微信小程序入门 第一个页面搭建
  • 原文地址:https://www.cnblogs.com/ghj1976/p/5822566.html
Copyright © 2011-2022 走看看