我想到的Netty功能,别人已经实现了
Netty是年初最先学习的框架,近期的图书租借系统想要用上聊天功能,实现一对一对话聊天,在用户登录服务端时,获取用户ip与id绑定,放入channelgroup,每次循环遍历这个ip对应的channel,否则返回false,在用户状态取到是否在线,在线状态属于handler消息功能。
1.一对一聊天
2.展示在线人数
3.登录验证
4.输入框优化
5.可支持表情
开源万岁
当寻找Netty一对一聊天功能实现的时候,除了重温下功能点,还能发现新的东西,一个小小的demo,别人却不是这么做的,细化到验证,还考虑到性能,看下实现效果页面
需要昵称输入,登录后不是简单的数据新增
private static ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
private static ConcurrentMap<Channel, UserInfo> userInfos = new ConcurrentHashMap<>();
private static AtomicInteger userCount = new AtomicInteger(0);
读写锁;
并发包;
原子计数;
因为最终实现用户的在线人数统计,用了原子类的AtomicInteger
private static AtomicInteger uidGener = new AtomicInteger(1000);
private boolean isAuth = false; // 是否认证
private long time = 0; // 登录时间
private int userId; // UID
private String nick; // 昵称
private String addr; // 地址
private Channel channel;// 通道
登录用户信息,确定昵称,获取ip,每一个用户ip,channel一一对应放入channelGroup。
如何发送消息?
在消息处理Handler中,重写channelread0方法
1.获取是否存在此用户信息的channel
2.存在将用户id,昵称,接收到的消息广播到页面显示
3.消息不为null,读写锁加锁,找到当前用户的channel
4.遍历用户信息,通过netty写入回调返回
if (msg instanceof FullHttpRequest) {
handleHttpRequest(ctx, (FullHttpRequest) msg);
} else if (msg instanceof WebSocketFrame) {
handleWebSocket(ctx, (WebSocketFrame) msg);
}
将Handler接受接入到Server
1.定时关闭失效的channel
2.定时向客户端ping消息
Netty的消息处理流程
定义好父子线程组–>在childInitializer定义好相关处理通道处理器–>自己提供处理器在回调
现在开始回调
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
将group放入消息管道
ch.pipeline().addLast(defLoopGroup,
//请求解码器
new HttpServerCodec(),
//将多个消息转换成单一的消息对象
new HttpObjectAggregator(65536),
//支持异步发送大的码流,一般用于发送文件流
new ChunkedWriteHandler(),
//检测链路是否读空闲
new IdleStateHandler(60, 0, 0),
//处理握手和认证
new UserAuthHandler(),
//处理消息的发送
new MessageHandler()
);
}
});
定时处理失效消息
// 定时扫描所有的Channel,关闭失效的Channel
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
logger.info("scanNotActiveChannel --------");
UserInfoManager.scanNotActiveChannel();
}
}, 3, 60, TimeUnit.SECONDS);
// 定时向所有客户端发送Ping消息
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
UserInfoManager.broadCastPing();
}
}, 3, 50, TimeUnit.SECONDS);
前端页面没有什么变化。
1.绑定websocket
2.websocket调用onmessage处理消息
window.socket = new WebSocket("ws://localhost:9688/websocket")
处理技术:
1.线程池
2.Lambad表达式
3.读写锁提高性能
4.原子引用保证原子性,线程安全
debug
用户登录,判断是否是给定的消息类型
获取昵称,用户信息,code码
==success,保存用户信息
第一次登陆没有此用户id与channel,不广播消息
用户计数0 broadCastPing userCount: 0
当发送消息到页面时
触发定时消息广播,遍历size
处理消息ctx.fireChannelRead(frame.retain());
此时广播用户计数broadCastPing userCount: 1
websocket实现了真正意义上的客户端与服务器端的长连接,节省带宽,而关注内容本身
websocket:1--:双向数据传递;
2--:基于Http
3--:非浏览器场合
- 点赞
- 收藏
- 关注作者
评论(0)