You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
3.4 KiB
98 lines
3.4 KiB
|
3 years ago
|
package com.bx.imserver.netty;
|
||
|
3 years ago
|
|
||
|
3 years ago
|
import com.bx.imcommon.contant.RedisKey;
|
||
|
|
import com.bx.imcommon.enums.IMCmdType;
|
||
|
3 years ago
|
import com.bx.imcommon.model.IMSendInfo;
|
||
|
3 years ago
|
import com.bx.imserver.netty.processor.MessageProcessor;
|
||
|
|
import com.bx.imserver.netty.processor.ProcessorFactory;
|
||
|
3 years ago
|
import com.bx.imserver.util.SpringContextHolder;
|
||
|
3 years ago
|
import io.netty.channel.ChannelHandlerContext;
|
||
|
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||
|
|
import io.netty.handler.timeout.IdleState;
|
||
|
|
import io.netty.handler.timeout.IdleStateEvent;
|
||
|
|
import io.netty.util.AttributeKey;
|
||
|
|
import lombok.extern.slf4j.Slf4j;
|
||
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* WebSocket 长连接下 文本帧的处理器
|
||
|
|
* 实现浏览器发送文本回写
|
||
|
|
* 浏览器连接状态监控
|
||
|
|
*/
|
||
|
|
@Slf4j
|
||
|
3 years ago
|
public class IMChannelHandler extends SimpleChannelInboundHandler<IMSendInfo> {
|
||
|
3 years ago
|
|
||
|
3 years ago
|
/**
|
||
|
|
* 读取到消息后进行处理
|
||
|
|
*
|
||
|
|
* @param ctx
|
||
|
|
* @param sendInfo
|
||
|
|
* @throws Exception
|
||
|
|
*/
|
||
|
3 years ago
|
@Override
|
||
|
3 years ago
|
protected void channelRead0(ChannelHandlerContext ctx, IMSendInfo sendInfo) throws Exception {
|
||
|
3 years ago
|
// 创建处理器进行处理
|
||
|
3 years ago
|
MessageProcessor processor = ProcessorFactory.createProcessor(IMCmdType.fromCode(sendInfo.getCmd()));
|
||
|
3 years ago
|
processor.process(ctx,processor.transForm(sendInfo.getData()));
|
||
|
3 years ago
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 出现异常的处理 打印报错日志
|
||
|
|
*
|
||
|
3 years ago
|
* @param ctx
|
||
|
|
* @param cause
|
||
|
|
* @throws Exception
|
||
|
3 years ago
|
*/
|
||
|
|
@Override
|
||
|
3 years ago
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||
|
3 years ago
|
log.error(cause.getMessage());
|
||
|
|
//关闭上下文
|
||
|
|
//ctx.close();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 监控浏览器上线
|
||
|
|
*
|
||
|
3 years ago
|
* @param ctx
|
||
|
|
* @throws Exception
|
||
|
3 years ago
|
*/
|
||
|
|
@Override
|
||
|
3 years ago
|
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||
|
3 years ago
|
log.info(ctx.channel().id().asLongText() + "连接");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
3 years ago
|
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
|
||
|
3 years ago
|
AttributeKey<Long> attr = AttributeKey.valueOf("USER_ID");
|
||
|
|
Long userId = ctx.channel().attr(attr).get();
|
||
|
3 years ago
|
ChannelHandlerContext context = UserChannelCtxMap.getChannelCtx(userId);
|
||
|
3 years ago
|
// 判断一下,避免异地登录导致的误删
|
||
|
|
if(context != null && ctx.channel().id().equals(context.channel().id())){
|
||
|
|
// 移除channel
|
||
|
3 years ago
|
UserChannelCtxMap.removeChannelCtx(userId);
|
||
|
3 years ago
|
// 用户下线
|
||
|
|
RedisTemplate redisTemplate = SpringContextHolder.getBean("redisTemplate");
|
||
|
|
String key = RedisKey.IM_USER_SERVER_ID + userId;
|
||
|
|
redisTemplate.delete(key);
|
||
|
|
log.info("断开连接,userId:{}",userId);
|
||
|
|
}
|
||
|
3 years ago
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||
|
|
if (evt instanceof IdleStateEvent) {
|
||
|
|
IdleState state = ((IdleStateEvent) evt).state();
|
||
|
|
if (state == IdleState.READER_IDLE) {
|
||
|
|
// 在规定时间内没有收到客户端的上行数据, 主动断开连接
|
||
|
3 years ago
|
AttributeKey<Long> attr = AttributeKey.valueOf("USER_ID");
|
||
|
|
Long userId = ctx.channel().attr(attr).get();
|
||
|
|
log.info("心跳超时,即将断开连接,用户id:{} ",userId);
|
||
|
3 years ago
|
ctx.channel().close();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
super.userEventTriggered(ctx, evt);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|