腾讯TIM实现即时通信 v3+ts实践
目录
初始化sdk
功能描述
初始化
准备 SDKAppID
调用初始化接口
监听事件
发送消息
创建消息
创建文本消息
登录登出
功能描述
登录
登出
销毁
登录设置
获取会话列表
功能描述
获取会话列表
获取全量的会话列表
历史消息
功能描述
拉取消息列表
分页拉取指定会话的消息列表
根据指定的消息 sequence 或消息时间跳拉会话的消息列表
接收消息
功能描述
监听事件
取消监听事件
总结
初始化sdk
功能描述
在使用 IM SDK 的各项功能前,必须先进行初始化。
初始化
初始化 SDK 需要操作以下步骤:
- 准备 SDKAppID。
- 调用
TIM.create
初始化 SDK。 - 添加 SDK 事件监听器。
下面我们将分步骤依次为您详细讲解。
准备 SDKAppID
您必须拥有正确的 SDKAppID,才能进行初始化。
SDKAppID 是腾讯云 IM 服务区分客户帐号的唯一标识。我们建议每一个独立的 App 都申请一个新的 SDKAppID。不同 SDKAppID 之间的消息是天然隔离的,不能互通。
您可以在 即时通信 IM 控制台 查看所有的 SDKAppID,单击 创建新应用,可以创建新的 SDKAppID。
调用初始化接口
操作完上述步骤后,您可以调用 TIM.create 初始化 SDK。
接口
TIM.create(options);
参数 options 为 Object 类型,包含的属性值如下:
Name | Type | Description |
---|---|---|
SDKAppID | Number | 即时通信 IM 应用的 SDKAppID |
public tim: ChatSDK | undefinedprivate initTimSdk(SDKAppID: number) {let options = {SDKAppID,// 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID};// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例let tim = TIM.create(options); // SDK 实例通常用 tim 表示// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html#setLogLevel 接口的说明</a>tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用// 注册腾讯云即时通信 IM 上传插件tim.registerPlugin({ 'tim-upload-plugin': TIMUploadPlugin })this.tim = tim}
监听事件
SDK 进入 ready 状态时触发,接入侧监听此事件,然后可调用 SDK 发送消息等 API,使用 SDK 的各项功能
// 监听sdk准备完成的事件private bindTIMEvent() {this.tim?.on(TIM.EVENT.SDK_READY, this.handleSDKReady, this)}
SDK 收到推送的单聊、群聊、群提示、群系统通知的新消息,接入侧可通过遍历 event.data 获取消息列表数据并渲染到页面
private handleSDKReady = () => {console.log('sdk准备完成');this.onReady()console.log('执行');this.tim?.on(TIM.EVENT.MESSAGE_RECEIVED, this.handleMessageReceived, this)}private handleMessageReceived = (event: TextMessageEvent) => {console.log('接收到消息', event);this.messageReceived(event)}public messageReceived = (event: TextMessageEvent) => { }
发送消息
创建消息
创建文本消息
创建文本消息的接口,此接口返回一个消息实例,可以在需要发送文本消息时调用 发送消息 接口发送消息实例。
接口
tim.createTextMessage(options);
参数
参数 options 为 Object 类型,包含的属性值如下:
Name | Type | Default | Description |
---|---|---|---|
to | String | - | 消息接收方的 userID 或 groupID |
conversationType | String | - | 会话类型,取值TIM.TYPES.CONV_C2C (端到端会话)或TIM.TYPES.CONV_GROUP (群组会话) |
priority | String | TIM.TYPES.MSG_PRIORITY_NORMAL | 消息优先级 |
payload | Object | - | 消息内容的容器 |
cloudCustomData | String | '' | 消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到,v2.10.2起支持) |
payload 的描述如下:
Name | Type | Description |
---|---|---|
text | String | 消息文本内容 |
返回值
消息实例 Message。
示例
private getMessageOptions = (userID: string, payload: ITextPayload) => {return this.tim?.createTextMessage({to: userID,conversationType: TIM.TYPES.CONV_C2C,// 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)// 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST// priority: TIM.TYPES.MSG_PRIORITY_NORMAL,payload,// v2.20.0起支持C2C消息已读回执功能,如果您发消息需要已读回执,需购买旗舰版套餐,并且创建消息时将 needReadReceipt 设置为 trueneedReadReceipt: true// 消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到,v2.10.2起支持)// cloudCustomData: 'your cloud custom data'})}public sendMessage = async (userID: string, payload: ITextPayload) => {// 创建消息const messOption = this.getMessageOptions(userID, payload)await this.tim?.sendMessage(messOption!)console.log('发送成功');}public sendMessage = async (userID: string, payload: ITextPayload) => {// 创建消息const messOption = this.getMessageOptions(userID, payload)await this.tim?.sendMessage(messOption!)console.log('发送成功');}
返回 消息实例 Message。
登录登出
功能描述
用户登录 IM SDK 才能正常收发消息,登录需要用户提供 UserID、UserSig 等信息,具体含义请参见 登录鉴权。
登录
注意:
- 登录成功,需等待 sdk 处于 ready 状态后(监听事件 TIM.EVENT.SDK_READY)才能调用 sendMessage 等需要鉴权的接口。
- 如需支持多实例登录(允许在多个网页中同时登录同一帐号),请登录 即时通信 IM 控制台,找到相应 SDKAppID,选择应用配置>功能配置>登录与消息>登录设置>Web 端可同时在线个数配置实例个数。配置将在5分钟内生效。
接口
tim.login(options);
参数
参数 options 为 Object 类型,包含的属性值如下:
名称 | 类型 | 描述 |
---|---|---|
userID | String | 用户 ID。 |
userSig | String | 用户登录即时通信 IM 的密码,其本质是对 UserID 等信息加密后得到的密文。 具体生成方法请参见 生成 UserSig。 |
返回值
Promise
对象。
示例
public timLogin = async (options: TIMCoreLoginParams) => {//第一步登录sdkawait this.tim?.login(options)// 持久化相关密钥localStorage.setItem('TIMCoreLoginParams', JSON.stringify(options))this.userID = options.userIDthis.bindTIMEvent()}
实例生成后缓存登录态
private persistedLogin = () => {console.log('缓存');const TIMCoreLoginParams = JSON.parse(localStorage.getItem('TIMCoreLoginParams') || '{}')if (TIMCoreLoginParams.userID) {console.log('存在登录');this.timLogin(TIMCoreLoginParams)}}
登出
登出即时通信 IM,通常在切换帐号的时候调用,清除登录态以及内存中的所有数据。
注意:
- 调用此接口的实例会发布 SDK_NOT_READY 事件,此时该实例下线,无法收、发消息。
- 如果您在即时通信 IM 控制台配置的“Web 端实例同时在线个数”大于 1,且同一帐号登录了
a1
和a2
两个实例(含小程序端),当执行a1.logout()
后,a1
会下线,无法收、发消息。而a2
实例不会受影响。- 多实例被踢:基于第 2 点,如果“Web 端实例同时在线个数”配置为 2,且您的某一帐号已经登录了
a1
,a2
两个实例,当使用此帐号成功登录第三个实例a3
时,a1
或a2
中的一个实例会被踢下线(通常是最先处在登录态的实例会触发),这种情况称之为“多实例被踢”。假设a1
实例被踢下线,a1
实例内部会执行登出流程,然后抛出KICKED_OUT事件,接入侧可以监听此事件,并在触发时跳转到登录页。此时a1
实例下线,而a2
、a3
实例可以正常运行。
接口
tim.logout();
参数
无
返回值
Promise
对象。
示例
let promise = tim.logout();
promise.then(function(imResponse) {console.log(imResponse.data); // 登出成功
}).catch(function(imError) {console.warn('logout error:', imError);
});
销毁
销毁 SDK 实例,包括:登出,断开长连接,并释放所有资源。
接口
tim.destroy();
参数
无
返回值
Promise
对象。
示例
tim.destroy().then(() => {console.log('sdk destroyed');
});
关闭监听
public unBindTIMEvent = () => {this.tim?.off(TIM.EVENT.MESSAGE_RECEIVED, () => { })this.tim?.off(TIM.EVENT.SDK_READY, () => { })}
登录设置
默认情况下,不支持多实例登录,即如果此帐号已在其他页面登录,若继续在当前页面登录成功,有可能会将其他页面踢下线。用户被踢下线时会触发事件TIM.EVENT.KICKED_OUT
,用户可在监听到事件后做相应处理。示例如下:
let onKickedOut = function (event) {console.log(event.data.type);// TIM.TYPES.KICKED_OUT_MULT_ACCOUNT(Web 端,同一帐号,多页面登录被踢)// TIM.TYPES.KICKED_OUT_MULT_DEVICE(同一帐号,多端登录被踢)// TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED(签名过期)// TIM.TYPES.KICKED_OUT_REST_API(REST API kick 接口踢出。v2.20.0起支持)
};
tim.on(TIM.EVENT.KICKED_OUT, onKickedOut);
获取会话列表
功能描述
用户在登录 App 后,可以像微信或 QQ 那样展示最近会话列表,方便找到目标会话。
会话列表如下图所示:
会话列表功能主要分为获取会话列表、监听会话列表更新事件。核心数据结构 Conversation。
获取会话列表
接入侧可通过调用 getConversationList 接口主动获取会话列表。
获取全量的会话列表
// 获取会话列表async getSessionList() {console.log('aaaa');const { data: { conversationList } } = await this.timeCore.tim?.getConversationList()this.conversationList = conversationListconsole.log(this.conversationList, '数据');// 他没有回话并且不是客服if (conversationList.length == 0 && this.timeCore.userID !== 'admin') {this.conversationList.push({lastMessage: {},userProfile: {userID: 'admin',} as Profile})}const userId = this.conversationList[0].userProfile?.userIDconsole.log(conversationList[0], '--------');if (userId) {this.selectedKeys = [userId]this.getMessageHistoryList(userId)}},
历史消息
功能描述
SDK 既支持分页续拉消息列表,也支持根据指定的消息 sequence 或消息时间跳拉消息列表。
云端存储的历史消息有存储时长的限制:
- 体验版:免费存储 7 天,不支持延长
- 专业版:免费存储 7 天,支持延长
- 旗舰版:免费存储 30 天,支持延长
说明:
- 延长历史消息存储时长是增值服务,您可以登录 即时通信 IM 控制台 修改相关配置,具体计费说明请参加 增值服务资费 。
- 富媒体消息(图片、文件、语音等)对应的文件存储时长,与历史消息存储时长保持一致。
拉取消息列表
分页拉取指定会话的消息列表
分页拉取指定会话的消息列表的接口,当用户进入会话首次渲染消息列表或者用户“下拉查看更多消息”时,需调用该接口。
注意:
该接口可用于"拉取历史消息",每次调用 SDK 最多返回20条消息。
接口
tim.getMessageList(options);
参数
参数 options 为 Object 类型,包含的属性值如下:
名称 | 类型 | 描述 |
---|---|---|
conversationID | String | 会话 ID。会话 ID 组成方式:
|
nextReqMessageID | String | undefined | 用于分页续拉的消息 ID。第一次拉取时该字段不要填值,续拉时填入上次调用 getMessageList 接口返回的该字段的值。 |
返回值
Promise
对象。
示例
async getMessageHistoryList(userId: string) {const data = await this.timeCore.tim?.getMessageList({ conversationID: `C2C${userId}` })this.historMessage = data.data.messageListconsole.log(data, '我是历史记录');}
// 下拉查看更多消息
let promise = tim.getMessageList({conversationID: 'C2Ctest', nextReqMessageID});
promise.then(function(imResponse) {const messageList = imResponse.data.messageList; // 消息列表。const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
});
根据指定的消息 sequence 或消息时间跳拉会话的消息列表
根据指定的消息 sequence 或 消息时间拉取会话的消息列表的接口。
注意:
v2.20.0起支持。
接口
tim.getMessageListHopping(options);
参数
参数 options 为 Object 类型,包含的属性值如下:
名称 | 类型 | 描述 |
---|---|---|
conversationID | String | 会话 ID。会话 ID 组成方式:
|
sequence | Number | undefined | 用于拉群组会话漫游消息的起始 sequence。 |
time | Number | undefined | 消息的服务端时间,用于拉 C2C 会话漫游消息的起始时间。 |
direction | Number | 消息拉取方向,默认 0。
|
count | Number | undefined | 需要拉取的消息数量,默认值和最大值为15,即一次拉取至多返回15条消息。 |
返回值
Promise
对象。
示例
// 根据 sequence 拉群漫游消息,direction 0 向上拉,拉更旧的消息,direction 1 向下拉,拉更新的消息
let promise = tim.getMessageListHopping({conversationID: 'GROUPtest', sequence: xxx, count: 15, direction: 0});
promise.then(function(imResponse) {const messageList = imResponse.data.messageList; // 消息列表。
});
// 根据时间拉 C2C 会话漫游消息,direction 0 向上拉,拉更旧的消息,direction 1 向下拉,拉更新的消息
let promise = tim.getMessageListHopping({conversationID: 'C2Ctest', time: xxx, count: 15, direction: 0});
promise.then(function(imResponse) {const messageList = imResponse.data.messageList; // 消息列表。
});
接收消息
功能描述
接收消息需要通过事件监听实现。
监听事件
注意:
请在调用 login 接口前调用此接口监听事件,避免漏掉 SDK 派发的事件。
接口
tim.on(eventName, handler, context);
参数
名称 | 类型 | 描述 |
---|---|---|
eventName | String | 事件名称。所有的事件名称都存放在 TIM.EVENT 变量中,如需要查看可以使用 console.log(TIM.EVENT) 把所有的事件显示出来。事件列表。 |
handler | Function | 处理事件的方法,当事件触发时,会调用此 handler 进行处理。 |
context | * | undefined | 期望 handler 执行时的上下文 |
返回值
无
示例
let onMessageReceived = function(event) {// event.data - 存储 Message 对象的数组 - [Message]const messageList = event.data;messageList.forEach((message) => {if (message.type === TIM.TYPES.MSG_TEXT) {// 文本消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.TextPayload} else if (message.type === TIM.TYPES.MSG_IMAGE) {// 图片消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.ImagePayload} else if (message.type === TIM.TYPES.MSG_SOUND) {// 音频消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.AudioPayload} else if (message.type === TIM.TYPES.MSG_VIDEO) {// 视频消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.VideoPayload} else if (message.type === TIM.TYPES.MSG_FILE) {// 文件消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.FilePayload} else if (message.type === TIM.TYPES.MSG_CUSTOM) {// 自定义消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.CustomPayload} else if (message.type === TIM.TYPES.MSG_MERGER) {// 合并消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.MergerPayload} else if (message.type === TIM.TYPES.MSG_LOCATION) {// 地理位置消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.LocationPayload} else if (message.type === TIM.TYPES.MSG_GRP_TIP) {// 群提示消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.GroupTipPayload} else if (message.type === TIM.TYPES.MSG_GRP_SYS_NOTICE) {// 群系统通知 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.GroupSystemNoticePayload}});
};
tim.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived);
取消监听事件
接口
tim.off(eventName, handler, context, once);
参数
名称 | 类型 | 描述 |
---|---|---|
eventName | String | 事件名称。所有的事件名称都存放在 TIM.EVENT 变量中,如需要查看可以使用 console.log(TIM.EVENT) 把所有的事件显示出来。事件列表。 |
handler | Function | 处理事件的方法,当事件触发时,会调用此 handler 进行处理。 |
context | * | undefined | 期望 handler 执行时的上下文 |
once | Boolean | undefined | 是否只解绑一次 |
返回值
无
示例
let onMessageReceived = function(event) {// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面// event.name - TIM.EVENT.MESSAGE_RECEIVED// event.data - 存储 Message 对象的数组 - [Message]
};
tim.off(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived);
总结
- 引入pinia的聊天模块开始进行sdk初始化
- 在登录完成后 完成tim的登录 并且持久化登录
- 在顶层页面完成消息的接收,也就是监听消息的变化每次变化通知一下pina事件的分法
- 在页面收到action发过来的消息后,要把消息主动放在当前聊天记录里面
- 当选择一个新的联系人的时候要获取这个人的聊天信息
- 每次发送消息要注意清空输入框,并且把最新消息手动push到当前聊天数组中
import TIM, { ChatSDK } from 'tim-js-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';
import { ChartDefineStoreOptions, ITextPayload, TextMessageEvent, TIMCoreLoginParams } from './type';export default class TIMCore {public tim: ChatSDK | undefinedpublic userID = ''constructor(props: ChartDefineStoreOptions) {this.initTimSdk(props.SDKAppID)}private initTimSdk(SDKAppID: number) {let options = {SDKAppID,// 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID};// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例let tim = TIM.create(options); // SDK 实例通常用 tim 表示// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html#setLogLevel 接口的说明</a>tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用// 注册腾讯云即时通信 IM 上传插件tim.registerPlugin({ 'tim-upload-plugin': TIMUploadPlugin })this.tim = timthis.persistedLogin()}public timLoginout = () => {//退出登录this.tim?.logout()}public unBindTIMEvent = () => {this.tim?.off(TIM.EVENT.MESSAGE_RECEIVED, () => { })this.tim?.off(TIM.EVENT.SDK_READY, () => { })}private persistedLogin = () => {console.log('缓存');const TIMCoreLoginParams = JSON.parse(localStorage.getItem('TIMCoreLoginParams') || '{}')if (TIMCoreLoginParams.userID) {console.log('存在登录');this.timLogin(TIMCoreLoginParams)}}public timLogin = async (options: TIMCoreLoginParams) => {//第一步登录sdkawait this.tim?.login(options)// 持久化相关密钥localStorage.setItem('TIMCoreLoginParams', JSON.stringify(options))this.userID = options.userIDthis.bindTIMEvent()}// 监听sdk准备完成的事件private bindTIMEvent() {this.tim?.on(TIM.EVENT.SDK_READY, this.handleSDKReady, this)}private handleSDKReady = () => {console.log('sdk准备完成');this.onReady()console.log('执行');this.tim?.on(TIM.EVENT.MESSAGE_RECEIVED, this.handleMessageReceived, this)}public onReady = () => {}private handleMessageReceived = (event: TextMessageEvent) => {console.log('接收到消息', event);// 接收到消息后 最好手动设置成已读this.tim?.setMessageRead({conversationID: event.data[0].conversationID})this.messageReceived(event)}// 对外暴露接受消息的方法public messageReceived = (event: TextMessageEvent) => { }// 创建对应消息类型private getMessageOptions = (userID: string, payload: ITextPayload) => {return this.tim?.createTextMessage({to: userID,conversationType: TIM.TYPES.CONV_C2C,// 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)// 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST// priority: TIM.TYPES.MSG_PRIORITY_NORMAL,payload,// v2.20.0起支持C2C消息已读回执功能,如果您发消息需要已读回执,需购买旗舰版套餐,并且创建消息时将 needReadReceipt 设置为 trueneedReadReceipt: true// 消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到,v2.10.2起支持)// cloudCustomData: 'your cloud custom data'})}public sendMessage = async (userID: string, payload: ITextPayload) => {// 创建消息const messOption = this.getMessageOptions(userID, payload)await this.tim?.sendMessage(messOption!)console.log('发送成功');}
}
相关文章:
腾讯TIM实现即时通信 v3+ts实践
目录 初始化sdk 功能描述 初始化 准备 SDKAppID 调用初始化接口 监听事件 发送消息 创建消息 创建文本消息 登录登出 功能描述 登录 登出 销毁 登录设置 获取会话列表 功能描述 获取会话列表 获取全量的会话列表 历史消息 功能描述 拉取消息列表 分页拉取…...
华为OD机试 - 回文字符串(Java JS Python)
题目描述 如果一个字符串正读和反渎都一样(大小写敏感),则称它为一个「回文串」,例如: leVel是一个「回文串」,因为它的正读和反读都是leVel;同理a也是「回文串」art不是一个「回文串」,因为它的反读tra与正读不同Level不是一个「回文串」,因为它的反读leveL与正读不…...
APP测试的7大注意点。
1. 运行 1) App安装完成后的试运行,可正常打开软件。 2) App打开测试,是否有加载状态进度提示。 3) App⻚面间的切换是否流畅,逻辑是否正确。 4) 注册 同表单编辑⻚面 用户名密码⻓度 …...
设计模式-第4章(装饰模式)
装饰模式装饰模型装饰模式示例商场收银程序(简单工厂策略装饰模式实现)装饰模式总结装饰模型 装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为…...
【算法设计-分治】快速幂与龟速乘
文章目录1. 快速幂2. 龟速乘3. 快速幂取模4. 龟速乘取模5. 快速幂取模优化1. 快速幂 算法原理: 计算 311: 311 (35)2 x 335 (32)2 x 332 3 x 3仅需计算 3 次,而非 11 次 计算 310: 310 (35)235 (32)2 x 332 3 x 3仅需计算…...
基于新一代kaldi项目的语音识别应用实例
本文是由郭理勇在第二届SH语音技术研讨会和第七届Kaldi技术交流会上对新一代kaldi项目在学术及“部署”两个方面报告的内容上的整理。如果有误,欢迎指正。 文字整理丨李泱泽 编辑丨语音小管家 喜报:新一代Kaldi团队三篇论文均被语音顶会ICASSP-2023接…...
【GO】31.grpc 客户端负载均衡源码分析
这篇文章是记录自己查看客户端grpc负载均衡源码的过程,并没有太详细的讲解,参考价值不大,可以直接跳过,主要给自己看的。一.主要接口:Balancer Resolver1.Balancer定义Resolver定义具体位置为1.grpc源码对解析器(resol…...
PTA L1-058 6翻了(详解)
前言:内容包括:题目,代码实现,大致思路,代码解读 题目: “666”是一种网络用语,大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”,意思是“6翻了”࿰…...
【Origin科研绘图】如何快速绘制一个折线图 ||【前端特效】爱心篇 之 幸好有你 || 泰坦尼克号——乘客生存与否 预测 || PyCharm使用介绍
🎯作者主页:追光者♂ 🌸个人简介:在读计算机专业硕士研究生、CSDN-人工智能领域新星创作者🏆、2022年CSDN博客之星人工智能领域TOP4🌟、阿里云社区专家博主🏅 【无限进步,一起追光!】 🍎欢迎点赞👍 收藏⭐ 留言📝 🌿本篇,首先是:基于科研绘图工具O…...
一文解读电压放大器(电压放大器原理)
关于电压放大器的科普知识,之前讲过很多,今天为大家汇总一篇文章来详细的讲解电压放大器,希望大家对于电压放大器能有更清晰的认识。电压放大器是什么:电压放大器是一种常用的电子器件,它的主要作用是把输入信号的振幅…...
线上监控诊断神器arthas
目录 什么是arthas 常用命令列表 1、dashboard仪表盘 2、heapdump dumpJAVA堆栈快照 3、jvm 4、thread 5、memory 官方文档 安装使用 1、云安装arthas 2、获取需要监控进程ID 3、运行arthas 4、进入仪表盘 5、其他命令使用查看官方文档 什么是arthas arthas是阿…...
@Import注解的原理
此注解是springboot自动注入的关键注解,所以拿出来单独分析一下。 启动类的run方法跟进去最终找到refresh方法; 这里直接看这个org.springframework.context.support.AbstractApplicationContext#refresh方法即可,它下面有一个方法 invoke…...
平台总线开发(id和设备树匹配)
目录 一、ID匹配之框架代码 二、ID匹配之led驱动 三、设备树匹配 四、设备树匹配之led驱动 五、一个编写驱动用的宏 一、ID匹配之框架代码 id匹配(可想象成八字匹配):一个驱动可以对应多个设备 ------优先级次低 注意事项…...
TS泛型,原来就这?
一、泛型是什么?有什么作用? 当我们定义一个变量不确定类型的时候有两种解决方式: 使用any 使用any定义时存在的问题:虽然知道传入值的类型但是无法获取函数返回值的类型;另外也失去了ts类型保护的优势 使用泛型 泛型…...
关于算法学习和刷题的建议
大家好,我是方圆。最近花时间学了学算法,应该算是我接触Java以来第一次真正的学习它,这篇帖子我会说一些我对算法学习的理解,当然这仅仅是浅浅的入算法的门,如果想深挖或者是有基础的人想提升自己,我觉得这…...
2023年“网络安全”赛项浙江省金华市选拔赛 任务书
2023年“网络安全”赛项浙江省金华市选拔赛 任务书 任务书 一、竞赛时间 共计3小时。 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段单兵模式系统渗透测试 任务一 Windows操作系统渗透测试 任务二 Linux操作系统渗透测试 任务三 网页渗透 任务四 Linux系统…...
http协议简介
http 1.简介 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处…...
CSDN 第三十一期竞赛题解
第二次参加 总分77.5,主要是在最后一题数据有误,花费了巨量时间… 参加的另一次比赛最后一道题目也出现了一点问题,有点遗憾。 题解 T1:最优利润值 你在读的经营课程上,老师布置了一道作业。在一家公司的日常运营中&…...
EM_ASM系列宏定义(emscripten)
2.5 EM_ASM系列宏很多编译器支持在C/C代码直接嵌入汇编代码,Emscripten采用类似的方式,提供了一组以“EM_ASM”为前缀的宏,用于以内联的方式在C/C代码中直接嵌入JavaScript代码。2.5.1 EM_ASMEM_ASM使用很简单,只需要将欲执行的Ja…...
Batchnorm和Layernorm的区别
在深度学习训练中,我们经常会遇到这两个归一化操作,他们之间有什么区别呢?我们来简单介绍一下: BatchNorm: 在深度学习训练的时候我们的数据如果没有经过预处理,有可能会出现梯度消失或者梯度爆炸的情况&…...
高级前端面试题汇总
iframe 有那些优点和缺点? iframe 元素会创建包含另外一个文档的内联框架(即行内框架)。 优点: 用来加载速度较慢的内容(如广告)可以使脚本可以并行下载可以实现跨子域通信 缺点: iframe 会…...
HTML#5表单标签
一. 表单标签介绍表单: 在网页中主要负责数据采集功能,使用<form>标签定义表单表单项: 不同类型的input元素, 下拉列表, 文本域<form> 定义表单<input> 定义表单项,通过typr属性控制输入形式<label> 为表单项定义标注<select> 定义下拉列表<o…...
ONNX可视化与编辑工具
ONNX可视化与编辑工具netrononnx-modifier在模型部署的过程中,需要使用到ONNX模型,下面给大家推荐两个ONNX可视化与编辑工具,其中,netron仅支持模型的可视化,onnx-modifier支持ONNX的可视化与编辑。 netron Netron是…...
Verilog 学习第五节(串口接收部分)
小梅哥串口部分学习part2 串口通信接收原理串口通信接收程序设计与调试巧用位操作优化串口接收逻辑设计串口接收模块的项目应用案例串口通信接收原理 在采样的时候没有必要一直判断一个clk内全部都是高/低电平,如果采用直接对中间点进行判断的话,很有可能…...
AIX系统常见漏洞修复(exec、rlogin、rsh、ftp、telnet远端服务运行中)
漏洞:1.1 SSH 服务支持弱加密算法 1. 使用telnet 登录2.vi /etc/ssh/sshd_config 最后添加一下内容(去掉 arcfour、arcfour128、arcfour256 等弱加密算法) Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast…...
IEEE SLT 2022论文丨如何利用x-vectors提升语音鉴伪系统性能?
分享一篇IEEE SLT 2022收录的声纹识别方向的论文,《HOW TO BOOST ANTI-SPOOFING WITH X-VECTORS》由AuroraLab(极光实验室)发表。 来源丨AuroraLab AuroraLab源自清华大学电子工程系与新疆大学信息科学与工程学院,以说话人识别和…...
设计模式(十三)----结构型模式之桥接模式
1 概述 现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来设计类的关系: 我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。 试…...
倾向得分匹配案例分析
一、倾向得分匹配法说明 倾向得分匹配模型是由Rosenbaum和Rubin在1983年提出的,首次运用在生物医药领域,后来被广泛运用在药物治疗、计量研究、政策实施评价等领域。倾向得分匹配模型主要用来解决非处理因素(干扰因素)的偏差。 …...
基于SpringCloud的可靠消息最终一致性04:项目基础代码
上一节给出了项目需求和骨架代码,这一节来接着看基础代码。骨架代码和基础代码最主要的区别是:骨架代码都是数据库脚本、POM依赖文件、配置文件内容、运维脚本等,而基础代码则是和业务有关联,但并非关键代码的部分。 这些代码不用一个个地看,主要是看看结构就行。 图二十五…...
操作系统权限提升(十八)之Linux提权-内核提权
Linux 内核提权 Linux 内核提权原理 内核提权是利用Linux内核的漏洞进行提权的,内核漏洞进行提权一般包括三个环节: 1、对目标系统进行信息收集,获取到系统内核信息及版本信息; 2、根据内核版本获取其对应的漏洞以及EXP 3、使…...
成都网站制作成都网站制作/属于b2b的网站有哪些
知识点:http 模块,请求头,响应头,响应体,fs 文件系统模块。 思路:根据请求的路径响应不同的数据 知识铺垫: node_fs文件系统模块_游小北的博客-CSDN博客 node_http服务_游小北的博客-CSDN博客…...
男女做那个什么的视频网站/奇葩网站100个
local machine/software/microsoft/windows/currentversion/explorer/namespac 建立主键 745FFO40-5081-101B-9F08-00AA002F954E 再把默认的主键值设为"回收站",重启 转载于:https://www.cnblogs.com/linbaba/archive/2013/01/30/2883224.html...
国内wordpress最好的主题/免费开源网站
步骤如下: 一、编译安装两个mysql,步骤如下 下载Mysql ,此处以Mysql-6.0.11-alpha.tar.gz 为例 安装第一个数据库(主数据库) (红色部分为默认数据库文件路径,可改成其他如:data、var等) tar zxvf mysql-6.0.11-alpha.t…...
网站跳出率计算/seo费用
php session 错误更新时间:2009年05月21日 12:59:31 作者:关于session的问题集锦解决方案1.错误提示Warning: Cannot send session cookie - headers already sentWarning: Cannot send session cache limiter - headers already sent分析及解决办法这…...
广州网站建设.com/智能建站abc
一、Linux历史 Unix强大的根本原因: 1、简洁,仅仅提供几百个系统调用并且有一个非常明确的设计目的 2、文件对待所有东西,通过一套相同的系统调用接口来进行对数据和设备的操作 3、由于用C语言编写,移植性强 4、进程创建非常迅速&…...