java nio netty 教程,4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了),netty实现...
4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了),netty实现
你好,我是彤哥,本篇是netty系列的第四篇。
欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识。
简介
上一章我们一起学习了Java中的BIO/NIO/AIO的故事,本章将带着大家一起使用纯纯的NIO实现一个越聊越上瘾的“群聊系统”。
业务逻辑分析
首先,我们先来分析一下群聊的功能点:
(1)加入群聊,并通知其他人;
(2)发言,并通知其他人;
(3)退出群聊,并通知其他人;
一个简单的群聊系统差不多这三个功能足够了,为了方便记录用户信息,当用户加入群聊的时候自动给他分配一个用户ID。
业务实现
上代码:
// 这是一个内部类
private static class ChatHolder {
// 我们只用了一个线程,用普通的HashMap也可以
static final Map USER_MAP = new ConcurrentHashMap<>();
/**
* 加入群聊
* @param socketChannel
*/
static void join(SocketChannel socketChannel) {
// 有人加入就给他分配一个id,本文来源于公从号“彤哥读源码”
String userId = "用户"+ ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
send(socketChannel, "您的id为:" + userId + "\n\r");
for (SocketChannel channel : USER_MAP.keySet()) {
send(channel, userId + " 加入了群聊" + "\n\r");
}
// 将当前用户加入到map中
USER_MAP.put(socketChannel, userId);
}
/**
* 退出群聊
* @param socketChannel
*/
static void quit(SocketChannel socketChannel) {
String userId = USER_MAP.get(socketChannel);
send(socketChannel, "您退出了群聊" + "\n\r");
USER_MAP.remove(socketChannel);
for (SocketChannel channel : USER_MAP.keySet()) {
if (channel != socketChannel) {
send(channel, userId + " 退出了群聊" + "\n\r");
}
}
}
/**
* 扩散说话的内容
* @param socketChannel
* @param content
*/
public static void propagate(SocketChannel socketChannel, String content) {
String userId = USER_MAP.get(socketChannel);
for (SocketChannel channel : USER_MAP.keySet()) {
if (channel != socketChannel) {
send(channel, userId + ": " + content + "\n\r");
}
}
}
/**
* 发送消息
* @param socketChannel
* @param msg
*/
static void send(SocketChannel socketChannel, String msg) {
try {
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put(msg.getBytes());
writeBuffer.flip();
socketChannel.write(writeBuffer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务端代码
服务端代码直接使用上一章NIO的实现,只不过这里要把上面实现的业务逻辑适时地插入到相应的事件中。
(1)accept事件,即连接建立的时候,说明加入了群聊;
(2)read事件,即读取数据的时候,说明有人说话了;
(3)连接断开的时候,说明退出了群聊;
OK,直接上代码,为了与上一章的代码作区分,彤哥特意加入了一些标记:
public class ChatServer {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
// 将accept事件绑定到selector上
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// 阻塞在select上
selector.select();
Set selectionKeys = selector.selectedKeys();
// 遍历selectKeys
Iterator iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
// 如果是accept事件
if (selectionKey.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
SocketChannel socketChannel = ssc.accept();
System.out.println("accept new conn: " + socketChannel.getRemoteAddress());
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
// 加入群聊,本文来源于公从号“彤哥读源码”
ChatHolder.join(socketChannel);
} else if (selectionKey.isReadable()) {
// 如果是读取事件
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 将数据读入到buffer中
int length = socketChannel.read(buffer);
if (length > 0) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
// 将数据读入到byte数组中
buffer.get(bytes);
// 换行符会跟着消息一起传过来
String content = new String(bytes, "UTF-8").replace("\r\n", "");
if (content.equalsIgnoreCase("quit")) {
// 退出群聊,本文来源于公从号“彤哥读源码”
ChatHolder.quit(socketChannel);
selectionKey.cancel();
socketChannel.close();
} else {
// 扩散,本文来源于公从号“彤哥读源码”
ChatHolder.propagate(socketChannel, content);
}
}
}
iterator.remove();
}
}
}
}
测试
打开四个XSHELL客户端,分别连接telnet 127.0.0.1 8080,然后就可以开始群聊了。
彤哥发现,自己跟自己聊天也是会上瘾的,完全停不下来,不行了,我再去自聊一会儿^^
总结
本文彤哥跟着大家一起实现了“群聊系统”,去掉注释也就100行左右的代码,是不是非常简单?这就是NIO网络编程的魅力,我发现写网络编程也上瘾了^^
问题
这两章我们都没有用NIO实现客户端,你知道怎么实现吗?
提示:服务端需要监听accept事件,所以需要有一个ServerSocketChannel,而客户端是直接去连服务器了,所以直接用SocketChannel就可以了,一个SocketChannel就相当于一个Connection。
最后,也欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识。
相关文章暂无相关文章
java nio netty 教程,4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了),netty实现...相关推荐
- java channel源码_彤哥说netty系列之Java NIO核心组件之Channel
你好,我是彤哥,本篇是netty系列的第五篇. 欢迎来我的工从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Ja ...
- java channel源码_5. 彤哥说netty系列之Java NIO核心组件之Channel
你好,我是彤哥,本篇是netty系列的第五篇. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Java NIO的核心组件之一--Channel. 思维转变 首先, ...
- java 仿qq庅,4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了)
你好,我是彤哥,本篇是netty系列的第四篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们一起学习了Java中的BIO/NIO/AIO的故事,本章将带着大家一起使 ...
- java netty教程_明哥教学 - Netty简单入门教程
作为一个正在Java路上摸爬滚打的小菜鸡,之前在项目中也用过Netty,也因为Netty报名阿里的中间件大赛,但终究功力太浅,最终不了了之,最近工作中又遇到了Netty的小姐妹Mina.此时楼主觉得N ...
- java se13安装教程_在Linux发行版中安装Java 13/OpenJDK 13的方法
本文介绍在Linux发行版Ubuntu 18.04/16.04.Debian 10/9.CentOS 7/8.Fedora 31/30/29中安装Java 13/OpenJDK 13.Java SE ...
- java转安卓快吗_安卓Kotlin开发系列之Java快速转Kotlin
原标题:安卓Kotlin开发系列之Java快速转Kotlin 自从Kotlin被宣布为Android开发语言的官方支持后,如今可谓是火的一塌糊涂,作为一名Android程序员,如何快速爬坑?今天为大家 ...
- 我的世界java版按键教程视频_我的世界(电脑Java版)execute指令教程
注:该教程基于Java V1.16.3 通常可以兼容1.13+的版本 1.9-1.12可能会有不兼容,出现问题可以在评论区提问.如果1.12及以下的玩家较多,以后会专门出一个针对1.12及以下的教 ...
- java后端开发教程_【后端开发】详细讲解JAVA中方法重载概念——简单易懂
1.什么方法重载? 方法的重载指的是方法名一样,但是参数类型不一样 1.1.attack方法重载 有一种英雄,叫做物理攻击英雄 ADHero,为ADHero 提供三种方法. public void a ...
- java 只有日期的类_【你不知道的事系列】Java中处理日期的类
Java中提供了一系列用于处理日期.时间的类,包括创建日期,时间对象,获取系统当前日期,时间等操作 Date类: 位于java.util.Date,从JDK1.0起就存在了,但现在它的大部分构造器,方 ...
最新文章
- 【响应式Web前端设计】设置图片间隙为0
- 自动生成网络拓扑图开源_为视频自动生成字幕,一款神奇的开源工具!
- mysql 数据库还原 不齐_请教mysql数据库还原问题。
- 【渝粤教育】 广东开放大学21秋期末考试管理学基础10241k2
- 百度贴吧 2017 前贴子无法访问;网易腾讯游戏获批;苹果反垄断案败诉 | 极客头条...
- 为什么互联网公司需要测试人员?
- Android MVP和Dagger2
- 目标检测(十三)--MultiPathNet
- Atitit 项目沟通管理 艾提拉总结 目录 1. 项目中沟通对象	2 1.1. 主要为项目干系人 产品部门 运营部门组员等	2 1.2. 适当越级沟通, 与高层直接沟通	3 2. 沟通频率	3
- 梨花风起正清明,清明习俗知多少?
- 流光容易把人抛,红了樱桃,绿了芭蕉
- php创建微信公众号管理系统-序言
- 如果这篇文章说不清epoll的本质,那就过来掐死我吧
- Groory语言关于省略的知识点
- Android 8.1 DisplayPowerController(五) 自动调节亮度(2)——算法
- 攻防世界 —— Crypto新手练习区7题(不仅仅是Morse)题解
- 腾讯云硬盘挂载宝塔命令
- 服务器端和客户端互发消息,Socket编程实现简单的服务器与客户端互发消息
- slf4j简单介绍(2)-使用
- java反斜杠_如何在字符串中使用反斜杠(\)?