[TOC]
## 测试工具
推荐测试工具:http://coolaf.com/tool/chattest
项目启动后的websocket地址:
![](https://img.kancloud.cn/a5/72/a572b9280d2a952c325429e0bceb4924_895x552.png)
一直发送消息就不会断开链接,Netty读写空闲的时候,可以通过设置主动断开连接。
## 对接流程
![](https://img.kancloud.cn/b9/95/b9955bdf72ff9b2956c9f889d99f00d0_1132x327.png)
### 消息类型
代码中预设了以下几种action:
```java
public enum MsgActionEnum {
CONNECT(1, "第一次(或重连)初始化连接"),
CHAT(2, "聊天消息"),
SIGNED(3, "消息签收"),
KEEPALIVE(4, "客户端保持心跳"),
PULL_FRIEND(5, "拉取好友");
public final Integer type;
public final String content;
MsgActionEnum(Integer type, String content){
this.type = type;
this.content = content;
}
public Integer getType() {
return type;
}
}
```
## 发送测试
### 建立连接
```json
{
"action": "1",
"chatMsg": {
"senderId": "10000",
"msg": "这是一条登录消息",
"receiverId": null
},
"extand": null
}
```
测试结果:
```
客户端被移除:channel id 为:c999a1cc
005056fffec00008-00005328-0000000b-38c05956b8a7fe83-7e0ea4d9
UserId:10000,ChannelId:005056fffec00008-00005328-0000000b-38c05956b8a7fe83-7e0ea4d9
进入写空闲......
进入读空闲......
进入写空闲......
channel 关闭之前:users 的数量为:1
channel 关闭之后:users 的数量为:0
客户端被移除:channel id 为:7e0ea4d9
```
#### `action = 1`存在的意义是什么?
```java
if(MsgActionEnum.CONNECT.type.equals(action)){
//2.1 当websocket 第一次open的时候,初始化channel,把用的channel 和 userid 关联起来
String senderId = dataContent.getChatMsg().getSenderId();
UserChanelRel.put(senderId,channel);
//测试
for (Channel c: users) {
log.info(c.id().asLongText());
}
UserChanelRel.output();
}
```
把消息的发送者放到一个map中,标记该用户的login状态。
### 聊天消息
```json
{
"action": "2",
"chatMsg": {
"senderId": "10000",
"receiverId": 10086,
"msg": "天若有情天亦老"
},
"extand": null
}
```
### 签收消息
```json
{
"action": "3",
"chatMsg": {
"senderId": "10000",
"receiverId": null,
"msg": null
},
"extand": 23549256,224244
}
```
通过接口获取到的消息清单,标记为签收状态,消息编号存放到`extand`属性中。
### 心跳检测
```json
{
"action": "4",
"chatMsg": {
"senderId": "10000",
"receiverId": null,
"msg": "心跳保持"
},
"extand": null
}
```
需要与服务端保持连接,否则读写均空闲的时候,服务端就会主动断开链接。
```
/**
* 用于检测channel 的心跳handler
* 继承ChannelInboundHandlerAdapter,目的是不需要实现ChannelRead0 这个方法
*/
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if(evt instanceof IdleStateEvent){
IdleStateEvent event = (IdleStateEvent)evt;//强制类型转化
if(event.state()== IdleState.READER_IDLE){
System.out.println("进入读空闲......");
}else if(event.state() == IdleState.WRITER_IDLE) {
System.out.println("进入写空闲......");
}else if(event.state()== IdleState.ALL_IDLE){
System.out.println("channel 关闭之前:users 的数量为:"+ChatHandler.users.size());
Channel channel = ctx.channel();
//资源释放
channel.close();
System.out.println("channel 关闭之后:users 的数量为:"+ChatHandler.users.size());
}
}
}
}
```
- 简介
- 更新说明
- 其他作品
- 第一部分 Java框架基础
- 第一章 Java基础
- 多线程实战
- 尝试一下Guava带返回值的多线程处理类ListenableFuture
- LocalDate和Date有什么区别
- JAVA8接口增强实践
- 第二章 Spring框架基础
- MVC究竟是个啥?
- @ApiImplicitParam
- 七种方式,教你在SpringBoot初始化时搞点事情!
- Spring事务状态
- maven
- Mybatis小总结
- mybatis-plus的使用
- 第三章 SpringSecurity实战
- 基于SpringSecurity+jwt的用户认证
- spring-security-oauth2
- 第四章 数据库
- mysql
- mysql授权
- mysql数据库三个关键性能指标--TPS\QPS\IOPS
- 梳理一下那些年Mysql的弱语法可能会踩的坑
- 关于Mysql的“字符串”数值的转换和使用
- 凭这一文咱把事务讲透
- Mysql性能优化
- 查询性能优化
- 不常用的一些语法
- elasticsearch
- elasticsearch文档操作
- 索引的基本操作
- java操作ElaticSearch
- elasticsearch中的各种查询
- DB与ES混合应用可能存在的问题及解决方案探索
- 使用es必须要知道的一些知识点:索引篇
- Es中的日期操作
- MongoDB
- 入门篇(了解非关系型数据库 NoSQL - MongoDB)
- 集群分片 (高级篇)
- 互联网大厂的建表规范
- 第五章 中间件
- nginx
- nginx动静分离配置,这个雷你踩过吗?
- Canal
- Sharding-jdbc
- 水平分库实践
- kafka
- 第六章 版本管理
- git
- Not currently on any branch 情况提交版本
- 第七章 IO编程
- 第八章 JVM实战调优
- jvisualvm
- jstat
- 第二部分 高级项目实战篇
- 第一章 微信开发实战
- 第二章 文件处理
- 使用EasyExcel处理导入导出
- 第三章 踩坑指南
- 邮件发送功能
- 第三部分 架构实战篇
- 第一章 架构实战原则
- 接口防止重复调用的一种方案
- 第二章 高并发缓存一致性管理办法
- 第三章 异地多活场景下的数据同步之道
- 第四章 用户体系
- 集成登录
- auth-sso的管理
- 第五章 分库分表场景
- 第六章 秒杀与高并发
- 秒杀场景
- 第七章 业务中台
- 中台的使用效果是怎样的?
- 通用黑白名单方案
- 第八章 领域驱动设计
- 第十一章 微服务实战
- Nacos多环境管理之道
- logback日志双写问题及Springboot项目正确的启动方式
- 第四部分 优雅的代码
- java中的链式编程
- 面向对象
- 开发原则
- Stream操作案例分享
- 注重性能的代码
- 第五部分 谈谈成长
- 新手入门指北
- 不可不知的调试技巧
- 构建自己的知识体系
- 我是如何做笔记的
- 有效的提问
- 谨防思维定势
- 学会与上级沟通
- 想清楚再去做
- 碎片化学习
- 第六部分 思维导图(付费)
- 技术基础篇
- 技术框架篇
- 数据存储篇
- 项目实战篇
- 第七部分 吾爱开源
- 7-1 麻雀聊天
- 项目启动
- 前端登录无请求问题解决
- websocket测试
- 7-2 ocp微服务框架
- evm框架集成
- 项目构建与集成
- zentao-center
- 二次开发:初始框架的搭建
- 二次开发:增加细分菜单、权限到应用
- 7-3 书栈网
- 项目启动
- 源码分析
- 我的书架
- 文章发布机制
- IM
- 第八章 团队管理篇
- 大厂是怎么运作的
- 第九章 码山有道
- 简历内推
- 联系我内推
- 第十章 学点前端
- Vue