即时通讯(Instant Messaging)是一种基于互联网的即时交流消息的业务。
实时聊天交互功能是市面上主流APP的重要功能之一,人们所熟悉的就是微信,QQ的聊天消息系统,IM看似简单,技术开发绝非易事,海量并发,超低延时,消息必达等高实时性需求需要众多技术的应用合体;
IM结合RTC可以实现直播间场景的实时互动,感兴趣的小伙伴可以查阅RTC系列专题教程,结合需求进行IM+RTC服务联动的场景开发;
本文介绍如何使用 ZIM SDK 快速实现基本的消息收发功能。
ZIM SDK 提供了如下接入方案:

在此方案中,您需要通过您自己的业务系统实现以下业务逻辑:
进入即构官网,在【ZEGO控制台】创建项目,并申请有效的 AppID,这一步很关键,appid为应用的唯一标识,如身份证号,是应用的身份证明,用于明确你的项目及组织身份。zego提供的服务也是基于APP ID;
App ID的获取方式很简单,只需3~5分钟,在即构官网-我的项目-创建即可。创建的项目信息可用于SDK的集成和配置;
登录房间时必须 使用 Token 鉴权 ,可参考 Token 鉴权教程 。
为了方便开发阶段的调试,开发者可直接在 ZEGO 控制台获取临时 Token(有效期为 24 小时) 来使用,详情请参考 控制台(新版) - 项目管理 中的 “项目信息”。
此步骤以如何创建新项目为例,如果是集成到已有项目,可忽略此步。
1.创建一个文件夹作为项目文件夹,结构类似如下:
├── assets
│ ├── css
│ │ └── index.css # 页面的样式
│ └── js
│ ├── biz.js # 实现 im 业务功能
│ └── zim.js # zim sdk
├── index.html # 应用的前端页面文件
2.将以下代码拷贝到 “index.html” 文件中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<title>ZIM</title>
<link rel="stylesheet" href="assets/css/index.css" />
</head>
<body></body>
<script src="./assets/js/zim.js"></script>
<script src="./assets/js/biz.js"></script>
</html>
3.用浏览器打开 “index.html” 文件。
使用 npm 获取 SDK
1.执行 npm i zego-zim-web 命令安装依赖。
a.npm 下载包支持 typescript 语言(推荐)。
b.如果在 macOS 或 Linux 系统中执行 npm 命令失败,提示 “permission denied”,请在 npm 命令前加上 sudo 重新执行即可。
导入 SDK。
import { ZIM } from 'zego-zim-web';
或
const ZIM = require('zego-zim-web').ZIM;
以下流程中,我们以客户端 A 和 B 的消息交互为例,实现 1v1 通信功能:

API的正确调用时序是保证消息实时发送和接收的关键,也是用户实时“交互”体验的重要因素。
故开发者需按照以下完整时序图进行调用:

首先我们需要在项目中创建 ZIM 实例,一个实例对应的是一个用户,表示一个用户以客户端的身份登录系统。
例如,客户端 A、B 分别调用 create 接口,传入 AppID,创建了 A、B 的实例:
// 创建 ZIM 对象,传入 AppID
var appID = xxxx;
var zim = ZIM.create(appID)
在客户端登录前,开发者可以通过调用 on 接口,自定义 ZIM 中的事件回调,接收到 SDK 异常、消息通知回调等的通知。
// 错误消息回调
zim.on('error', function (zim, errorInfo) {
console.log(errorInfo.code, errorInfo.message);
});
// 连接状态变更回调
zim.on('connectionStateChanged', function (zim, state, event, extendedData) {
console.log(state, event, extendedData);
});
// 房间状态变更回调
zim.on('roomStateChanged', function (zim, state, event, extendedData, roomID) {
console.log(roomID, state, event, extendedData);
});
// 成员加入房间回调
zim.on('roomMemberJoined', function (zim, memberList, roomID) {
console.log(memberList, roomID);
});
// 成员离开房间回调
zim.on('roomMemberLeft', function (zim, memberList, roomID) {
console.log(memberList, roomID);
});
// 收到房间消息回调
zim.on('receiveRoomMessage', function (zim, messageList, fromRoomID) {
console.log(messageList, fromRoomID);
});
// 收到单聊通信的消息回调
zim.on('receivePeerMessage', function (zim, messageList, fromUserID) {
console.log(messageList, fromUserID);
});
// 令牌即将过期的提醒回调
zim.on('tokenWillExpire', function (zim, second) {
console.log(second);
// 可以在这里调用 renewToken 接口来更新 token
// 新 token 生成可以参考上文
zim.renewToken(token)
.then(function(token){
// 更新成功
})
.catch(function(err){
// 更新失败
})
});
创建实例后,客户端 A 和 B 需要登录 ZIM,只有登录成功后才可以开始发送、接收消息、更新 Token 等。
客户端需要使用各自的用户信息和 Token 进行登录。调用 login 接口进行登录,传入用户信息 ZIMUserInfo 对象,以及 Token 进行鉴权,鉴权通过后才能登录成功。
“userID”、“userName” 支持开发者自定义规则生成。建议开发者将 “userID” 设置为一个有意义的值,可将其与自己的业务账号系统进行关联。
如果 Token 过期,需要在 tokenWillExpire 即将过期回调接口中,调用 renewToken 接口,更新 Token 后才能正常使用 SDK。
// 登录时,需要开发者 按照 基础功能中的 "使用 Token 鉴权" 文档生成 token 即可
// userID 和 userName,最大 32 字节的字符串。仅支持数字,英文字符 和 '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '=', '-', '`', ';', '’', ',', '.', '<', '>', '/', ''。
var userInfo = { userID: '', userName: '' };
var token = '';
zim.login(userInfo, token)
.then(function () {
// 登录成功
})
.catch(function (err) {
// 登录失败
});
客户端 A 登录成功后,可以向客户端 B 发送消息。
目前 ZIM 支持的消息类型如下:
| 消息类型 | 说明 |
|---|---|
| ZIMMessage | 基类消息,包含如下属性:priority:消息优先级。type:消息类型。messageID:标识这条消息的唯一 ID。timestamp:发送时间。message:消息内容。senderUserID:消息发送者。conversationID:会话的 ID。conversationType:会话类型。 |
| ZIMTextMessage | 文本消息,是在基类的基础上添加了一个 String 类型的 “message” 参数,消息大小不超过 32 KB,发送频率限制为 10 次/秒。 |
| ZIMCommandMessage | 开发者可自定义数据类型的信令消息。信令消息是在基类的基础上添加了一个 Byte/Data 类型的 “message” 参数,消息大小不超过 5 KB,发送频率限制为 20 次/秒。 |
当前 Web/小程序(版本均为 1.2.0)的 SDK ,仅支持信令消息,不支持文本消息类型;同时也不支持发送离线消息的功能。
如果开发者需要使用 “Web/小程序”(当前 SDK 最新版本均为 1.2.0)SDK、与其它平台(iOS/Android/macOS/Windows 平台,当前 SDK 最新版本均为 2.0.0)SDK 进行消息互通,请统一使用信令(即 ZIMCommandMessage)消息,保证消息畅通。
客户端 A 可以调用 sendPeerMessage 接口,传入客户端 B 的 userID、消息内容等信息,即可发送一条消息到 B 的客户端。
// 发送单聊信息
var messageObj = { priority: 1, type: 1, message: '消息内容' };
var toUserID = '';
zim.sendPeerMessage(messageObj, toUserID)
.then(function (message) {
// 发送成功
})
.catch(function (err) {
// 发送失败
});
客户端 B 登录 ZIM 后,将会收到在 on 回调中设置的 receivePeerMessage 监听接口,收到客户端 A 发送过来的消息。
// 收到单聊消息的回调
zim.on('receivePeerMessage', function (zim, messageList, fromUserID) {
console.log(messageList, fromUserID);
});
如果客户端需要退出登录,直接调用 logout 接口即可。
zim.logout();
如果不需要 ZIM 实例,可直接调用 destroy 接口,销毁实例。
zim.destroy();
到这里,你已经完成了IM基本收发消息功能,快去找你的小伙伴互发消息体验吧~
ZEGO 提供 ZIM + RTC 服务联动的场景解决方案,公开语聊房、秀场直播等业务场景搭建的示例源码,帮助开发者能在极短的时间内搭建完美的业务场景。
同时ZIM提供免费体验版,点击联系商务获取体验资格,了解更多优惠活动;
获取Demo、开发文档、技术支持,访问即构文档中心;
注册即构ZEGO开发者帐号,快速开始...
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解