用netty实现聊天

news/2024/11/29 23:40:43/

1.引入netty依赖

<dependencies>
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.92.Final</version>
</dependency>
</dependencies>

2.准备一个服务端ChatServer和一个服务端处理器ChatServerHandler和若干个客户端ChatClient(有几个用户设置几个)和一个客户端处理器ChatClientHandler

服务端
public class ChatServer {public static void main(String[] args) {// 新建两个事件循环组,bossGroup 用于监听客户端的连接请求,将连接请求发送给 workerGroup 用于处理客户端连接的数据读写NioEventLoopGroup bossGroup = new NioEventLoopGroup();NioEventLoopGroup workGroup = new NioEventLoopGroup();ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workGroup);serverBootstrap.channel(NioServerSocketChannel.class);serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));ch.pipeline().addLast(new ChatServerHandler());}});// 服务端绑定9000端口serverBootstrap.bind(9000);}public void test(){NioEventLoopGroup bossGroup = new NioEventLoopGroup();NioEventLoopGroup workGroup = new NioEventLoopGroup();ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup,workGroup);serverBootstrap.channel(NioServerSocketChannel.class);serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {nioSocketChannel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));nioSocketChannel.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));nioSocketChannel.pipeline().addLast(new ChatServerHandler());}});serverBootstrap.bind(9001);}
}

服务端处理器

public class ChatServerHandler extends ChannelInboundHandlerAdapter {// 创建一个list集合存储连接上的所有客户端channelprivate static List<Channel> channels = new ArrayList<>();// 当有客户端连接上服务端,底层会调用此方法,执行此方法的逻辑// 这里大概的处理逻辑是:先添加新客户端channel到集合中,然后循环遍历list集合// 然后根据不同的channel发送不同的系统消息@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();channels.add(channel);channels.forEach(ch -> {if (ch == channel) {channel.writeAndFlush("恭喜您,上线成功");} else {ch.writeAndFlush("系统消息:[" + ch.remoteAddress() + "]客户端已上线");}});System.out.println("客户端[" + channel.remoteAddress() + "]请求连接");}// 当有客户端连断开连接,底层会调用此方法,执行此方法的逻辑// 这里大概的处理逻辑是:然后循环遍历list集合,找到已断开连接的channel并删除// 向集合内的channel发送系统消息@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();Iterator<Channel> iterator = channels.iterator();while (iterator.hasNext()) {Channel ch = iterator.next();if (ch == channel) {iterator.remove();}ch.writeAndFlush("系统消息:[" + channel.remoteAddress() + "]客户端已下线");}System.out.println("客户端[" + channel.remoteAddress() + "]断开连接");}// 当有客户端发送消息到服务端,底层会调用此方法,执行此方法的逻辑// 这里大概的处理逻辑是:循环遍历向集合中的channel(除发送消息的客户端)发送消息@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {Channel channel = ctx.channel();SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date = new Date(System.currentTimeMillis());String now = formatter.format(date);System.out.println(now+"收到用户[" + channel.remoteAddress() + "]发来的消息:" + msg.toString());channels.forEach(ch -> {if (ch != channel) {ch.writeAndFlush("消息时间:" + now + " 用户[" + channel.remoteAddress() + "]说:" + msg.toString());}});}//异常触发@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}

客户端

public class ChatClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup workGroup = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.group(workGroup);bootstrap.channel(NioSocketChannel.class);// 设置处理器bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {// 将字符串编解码器及客户端处理器添加到pipeline中ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));ch.pipeline().addLast(new ChatClientHandler());}});// 连接服务端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000);channelFuture.sync();// 获取客户端输入的内容,并发送至服务端(因为添加了字符串编解码器,所以此处可以直接发送字符串)Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()) {channelFuture.channel().writeAndFlush(scanner.nextLine());}}
}

客户端处理器

public class ChatClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println(msg.toString());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}

如果需要多个客户端用户,将客户端多复制几个就可以了.

启动时先启动服务端再启动客户端

 

 

 


http://www.ppmy.cn/news/71999.html

相关文章

ONNX模型推理使用多核CPU加速推理

目录 一、前言 二、准备 三、代码 四、推理时间比对 一、前言 对于嵌入式设备&#xff0c;将模型转成onnx后&#xff0c;可以方便的将pytorch或者tensorflow的模型在嵌入式设备上运行&#xff0c;但是onnx模型默认只调用一个CPU核心去做推理&#xff0c;所以有些嵌入式设备有…

4 个无质量损失的免费在线图像压缩器

本文内容&#xff1a;最佳在线图像优化器&#xff0c;无质量损失&#xff0c;可让您压缩 JPG、PNG 和 GIF 文件。 在线图像优化器工具可帮助您压缩图像而不会降低质量。并给出图像可以压缩多少的想法。 经过测试和比较的没有质量损失的最佳在线图像优化器 4 个无质量损失的免…

Android系统的问题分析笔记(7) - Android上的C++底层库都有啥 ?

问题 Android系统上的C底层库都有啥&#xff1f;&#xff08;此篇分析基础为Android 7.1.1系统源码&#xff09; 概述 在Android系统中&#xff0c;Bionic是最基础的C库&#xff0c;但它仅仅是基础库。对于开发者而已&#xff0c;工具库才是真正在编写Native程序时更多被使用…

程序员怎么学爬虫JS逆向

爬虫JS逆向&#xff08;也称为前端逆向、JS破解等&#xff09;是指通过分析JavaScript代码&#xff0c;破解前端加密算法或构造相应的模拟请求&#xff0c;从而有效地模拟人类用户完整的操作行为实现数据爬取。 以下是一些常见的爬虫JS逆向技术&#xff1a; 1、自动识别Javas…

使用Google浏览器开启New bing

简介 搭建 通过谷歌商店下载两个浏览器插件&#xff0c;一个用于修改请求头agent的插件和一个用于伪造来源的插件x-forwarded-for插件&#xff0c;当然类似的插件很多很多&#xff0c;我这里使用的两个插件是 User-Agent Switcher Header Editor 使用 User-Agent Switcher 插件…

【大数据之Hadoop】三十二、MapReduce生产经验

1 MapReduce跑的慢的原因 MapReduce程序效率的瓶颈在于两点&#xff1a; 1&#xff09;计算机性能&#xff1a;CPU、内存、磁盘、网络 2&#xff09;I/O操作优化 &#xff08;1&#xff09;数据倾斜 &#xff08;2&#xff09;Map运行时间太长&#xff0c;导致Reduce等待过久 …

【总结】Numpy2

Numpy 1. 数组和数的运算 array1 np.arange(1,10) array1 # array([1, 2, 3, 4, 5, 6, 7, 8, 9]) array1 10 # array([11, 12, 13, 14, 15, 16, 17, 18, 19]) array1 - 10 # array([-9, -8, -7, -6, -5, -4, -3, -2, -1]) array1 * 10 # array([10, 20, 30, 40, 50, 60, 70…

20230516----重返学习-react基础-业务开发思路

day-071-seventy-one-20230516-react基础-业务开发思路 react基础 MVVM(Vue) 与 MVC(React) MVVM&#xff1a; Model View ViewModel&#xff0c;双向数据驱动。 基本构成&#xff1a; Model&#xff1a;数据层View&#xff1a;视图层ViewModel&#xff1a;视图模型&#xff0…