• 如何实现一个IM


    如何实现一个IM

    Client + Data Transfer Protocol + Server 搞定这三个部分就能实现一个IM

    • Client: 根据支持PC、浏览器、手机等特性来决定支持的语言来实现

    • Transfer Protocol: http/tcp(ip)/)websocket + xml/json 来实现

    • Server: 主要承担Client信息记录、连接管理、信息路由等职责

    • Getway: 网关是用来实现异构IM互通,主要用于协议转换和交互. 可选.

    IM常用功能

    • 即时通讯 - 在用户和在线朋友之间来回发送信息
    • 聊天 - 创建用户与朋友的自定义聊天室
    • 网页链接 - 共享用户喜爱的网址
    • 支持图片 - 浏览朋友计算机中的图片
    • 支持声音 - 给朋友播放音乐
    • 支持文件传输 - 直接将文件发送给朋友,以便于共享
    • 交谈 - 使用 Internet,而不是电话,与朋友们进行真正的交谈
    • 影音串流内容 - 实时或准实时的股市行情或新闻

    数据传输协议选择 - XMPP

    我们简要说明一下XMPP协议

    Xmpp协议 —— 简单说来就是基于XML的一种实时通信协议,包含打包、解包消息,一般使用tcp/ip通讯。

    优缺点

    • 优点: 扩展性好
    • 缺点:XML冗余数据多,另外Xmpp协议定义的交互方式导致完成一次会话交互次数比较多,造成数据流量浪费;且不能修改二进制的问题,所以文件传输只能使用外部Http

    JID(Jabber Identifier, JID)

    Xmpp协议中定义的各种对象和实体(用户、Server、Gateway)都可以用唯一的JID标识,成为Jabber地址. 具体格式:

    [ node "@" ] domain [ "/" resource ]

    最常见的标识一个用户,比如:joseph@imserver/ipad .resource用来标识用户的特殊对象,比如位置或设备

    XML数据结构

    <stream>
    --------------------------
    	<presence></presence> 
    --------------------------
    	<message></message>
    --------------------------
    	<iq></iq> 
    --------------------------
    <stream>    
    

    每一条线分割标识一次会话

    要区分两个基本概念:XML流和XML节

    • XML流是整个网络交互的容器,包含了所有网络交互的XML元素,XMPP是以开头,结尾关闭流. 这是异步数据传输的一种标准方式.

    • XML节是通过XML流传输的一种结构化信息单元,比如<presence/>、<message/>、<iq/>

    • 比较特殊的是安全认证相关的元素,不被认为是XML节,主要用于协商传输层安全协议、简单认证与安全层协议和服务器回拨认证协议完成通信认证、加密等目的的数据交互

    流元素属性
    属性 初始方->接收方 接收方->初始方
    to 接收方的主机名 忽略
    from 忽略 接收方的主机名
    id 忽略 会话键值
    xml:lang 缺省语言 缺省语言
    version 支持XMPP1.0 支持XMPP1.0

    交互过程

    SENT (0): <stream:stream xmlns='jabber:client' to='127.0.0.1' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
    RECV (0): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="127.0.0.1" id="96fafe03" xml:lang="en" version="1.0"><stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism><mechanism>CRAM-MD5</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><auth xmlns="http://jabber.org/features/iq-auth"/><register xmlns="http://jabber.org/features/iq-register"/></stream:features>
    SENT (0): <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'>=</auth>
    RECV (0): <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09IjEyNy4wLjAuMSIsbm9uY2U9Illuc1Z4U2VyY2RSZVF2WTFSdlVTd21OSUdZVk50N2pNb2MwNG1WenAiLHFvcD0iYXV0aCIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=</challenge>
    SENT (0): <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>Y2hhcnNldD11dGYtOCx1c2VybmFtZT0idGVzdFVzZXIxIixyZWFsbT0iMTI3LjAuMC4xIixub25jZT0iWW5zVnhTZXJjZFJlUXZZMVJ2VVN3bU5JR1lWTnQ3ak1vYzA0bVZ6cCIsbmM9MDAwMDAwMDEsY25vbmNlPSJpL0FSanM3MWFXeXJlN2xhY3hSQ2NtVDROTVNlRXd1ay9hUUtwT3k4IixkaWdlc3QtdXJpPSJ4bXBwLzEyNy4wLjAuMSIsbWF4YnVmPTY1NTM2LHJlc3BvbnNlPWQ3NjZjMmZlZWY3YjI0ZWZmODMyYTdlY2ZiNWU1YzgyLHFvcD1hdXRo</response>
    RECV (0): <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD1kN2IxZjQzNWI4ODEwZDVkZTc0NmNjMzcwYmUzMGRjOQ==</success>
    SENT (0): <stream:stream xmlns='jabber:client' to='127.0.0.1' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' id='96fafe03' xml:lang='en'>
    RECV (0): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="127.0.0.1" id="96fafe03" xml:lang="en" version="1.0"><stream:features><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>
    SENT (0): <iq id='bBkWS-1' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>Smack</resource></bind></iq>
    RECV (0): <iq type="result" id="bBkWS-1" to="127.0.0.1/96fafe03"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>testuser1@127.0.0.1/Smack</jid></bind></iq>
    SENT (0): <iq id='bBkWS-3' type='set'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>
    RECV (0): <iq type="result" id="bBkWS-3" to="testuser1@127.0.0.1/Smack"/>
    User logged (0): testuser1@127.0.0.1:5222/Smack
    XMPPConnection authenticated (0)
    SENT (0):<iq id='bBkWS-5' type='get'><query xmlns='jabber:iq:roster'></query></iq>
    SENT (0): <presence id='bBkWS-6'></presence>
    RECV (0): <iq type="result" id="bBkWS-5" to="testuser1@127.0.0.1/Smack"><query xmlns="jabber:iq:roster"/></iq>
    RECV (0): <presence id="bBkWS-6" from="testuser1@127.0.0.1/Smack" to="testuser1@127.0.0.1/Smack"/>
    SmackClient.(68) - testUser1 login successful.
    SENT (0): <message to='testUser2@127.0.0.1' id='bBkWS-9' type='chat'><body>hello,too.</body><thread>090684cf-ba64-4c9b-a03d-edad92dc4ea6</thread></message>
    SmackClient.(159) - 向[testUser2]发送消息[hello,too.]
    

    安全

    TSL(传输层安全协议)

    XMPP 为防止篡改和偷听.TLS加密方法, 模拟了类似的其他"STARTTLS" 的扩展,如 IMAP [IMAP], POP3 [POP3]"STARTTLS"。扩展命名空间是'urn:ietf:params:xml:ns:xmpp-tls'.

    STARTTLS 是对纯文本通信协议的扩展。它提供一种方式将纯文本连接升级为加密连接(TLS或SSL),而不是另外使用一个端口作加密通信。

    交互过程:客户端先询问服务端是否支持TSL/SSL,如果服务端回复支持,那么客户端就以TSL/SSL的方式发送数据,否则以原来的方式发送数据

    TSL、SSL、STARTTLS区别和关系:TSL/SSL提供一种方式网络间的一个加密通信通道,STARTTLS可选择使用TSL/SSL

    想了解更多详情可点击进入 Xmpp官网

    服务器端选择

    客户端选择

    即可选择现成的开源实现,也可基于实现了XML的开源框架来定制开发.下面是几个例子.

    • spark
    • jwchat
    • conversejs
    • Strophe.js
    • iJab

    后续会对每个部分进行详细说明.

    参考资料

    Xmpp官网
    环信支持千万并发即使通讯的技术要点

  • 相关阅读:
    webpack入门(1)
    react基础(2)
    react基础(1)
    react入门(5)
    react入门(4)
    react入门(3)
    webstorm出现黑色块光标
    微信小程序——组件(二)
    微信小程序——组件(一)
    react-native 在Xcode上传到iTunes Connect里报错
  • 原文地址:https://www.cnblogs.com/lifepai/p/4389899.html
Copyright © 2020-2023  润新知