Netty案例-群聊天室
案例要求:
- 编写一个 Netty 群聊系统,实现服务器端和客户端之间的数据简单通讯
- 实现多人群聊
- 服务器端:可以监测用户上线,离线,并实现消息转发功能
- 客户端:可以发送消息给其它所有用户,同时可以接受其它用户发送的消息
1、聊天室服务端编写
NettyChatServer
-
package com.lagou.chat;
-
-
import io.netty.bootstrap.ServerBootstrap;
-
import io.netty.channel.*;
-
import io.netty.channel.nio.NioEventLoopGroup;
-
import io.netty.channel.socket.SocketChannel;
-
import io.netty.channel.socket.nio.NioServerSocketChannel;
-
import io.netty.handler.codec.string.StringDecoder;
-
import io.netty.handler.codec.string.StringEncoder;
-
-
/**
-
* 聊天室服务端
-
*/
-
public class NettyChatServer {
-
// 端口号
-
private int port;
-
-
public NettyChatServer(int port) {
-
this.port = port;
-
}
-
-
public void run() throws InterruptedException {
-
// 1. 创建bossGroup线程组: 处理网络事件--连接事件
-
EventLoopGroup bossGroup = null;
-
// 2. 创建workerGroup线程组: 处理网络事件--读写事件 2*处理器线程数
-
EventLoopGroup workerGroup = null;
-
try {
-
// 1. 创建bossGroup线程组: 处理网络事件--连接事件
-
bossGroup = new NioEventLoopGroup(1);
-
// 2. 创建workerGroup线程组: 处理网络事件--读写事件 2*处理器线程数
-
workerGroup = new NioEventLoopGroup(2);
-
// 3. 创建服务端启动助手
-
ServerBootstrap serverBootstrap = new ServerBootstrap();
-
// 4. 设置bossGroup线程组和workerGroup线程组
-
serverBootstrap.group(bossGroup, workerGroup)
-
.channel(NioServerSocketChannel.class) // 5. 设置服务端通道实现为NIO
-
.option(ChannelOption.SO_BACKLOG, 128) // 6. 参数设置
-
.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) // 6. 参数设置
-
.childHandler(new ChannelInitializer<SocketChannel>() {// 7. 创建一个通道初始化对象
-
-
protected void initChannel(SocketChannel ch) throws Exception {
-
// 8. 向pipeline中添加自定义业务处理handler
-
// 添加编解码器
-
ch.pipeline().addLast(new StringDecoder());
-
ch.pipeline().addLast(new StringEncoder());
-
-
ch.pipeline().addLast(new NettyServerHandler());
-
}
-
});
-
-
// 9. 启动服务端并绑定端口,同时将异步改为同步
-
// ChannelFuture future = serverBootstrap.bind(9999).sync();
-
ChannelFuture future = serverBootstrap.bind(port);
-
future.addListener(new ChannelFutureListener() {
-
-
public void operationComplete(ChannelFuture future) throws Exception {
-
if (future.isSuccess()) {
-
System.out.println("端口绑定成功");
-
} else {
-
System.out.println("端口绑定失败");
-
}
-
}
-
});
-
System.out.println("聊天室服务端启动成功");
-
// 10. 关闭通道(并不是真正意义上的关闭,而是监听通道关闭的状态)和关闭连接池
-
future.channel().closeFuture().sync();
-
} finally {
-
bossGroup.shutdownGracefully();
-
workerGroup.shutdownGracefully();
-
}
-
}
-
-
public static void main (String[]args) throws InterruptedException {
-
new NettyChatServer(9998).run();
-
}
-
}
-
NettyServerHandler
-
package com.lagou.chat;
-
-
import io.netty.channel.Channel;
-
import io.netty.channel.ChannelHandlerContext;
-
import io.netty.channel.SimpleChannelInboundHandler;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
/**
-
* 聊天室业务处理类
-
*/
-
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
-
public static List<Channel> channelList = new ArrayList<>();
-
-
/**
-
* 通道就绪事件
-
*
-
* @param ctx
-
* @throws Exception
-
*/
-
-
public void channelActive(ChannelHandlerContext ctx) throws Exception {
-
Channel channel = ctx.channel();
-
// 当有新的客户端连接的时候,将通道放入集合
-
channelList.add(channel);
-
System.out.println("[Server]:" channel.remoteAddress().toString().substring(1) "在线");
-
}
-
-
/**
-
* 通道未就绪--channel 下线
-
*
-
* @param ctx
-
* @throws Exception
-
*/
-
-
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-
Channel channel = ctx.channel();
-
// 当已有客户端断开连接的时候,就一处对应的通道
-
channelList.remove(channel);
-
System.out.println("[Server]:" channel.remoteAddress().toString().substring(1) "下线");
-
}
-
-
/**
-
* 通道读取事件
-
*
-
* @param ctx
-
* @param msg
-
* @throws Exception
-
*/
-
-
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
-
// 当前发送消息的通道,当前发送客户端的连接
-
Channel channel = ctx.channel();
-
for (Channel channel1 : channelList) {
-
// 排除自身通道
-
if (channel != channel1) {
-
channel1.writeAndFlush("[" channel.remoteAddress().toString().substring(1) "]说:" msg);
-
}
-
}
-
}
-
-
/**
-
* 异常处理事件
-
* @param ctx
-
* @param cause
-
* @throws Exception
-
*/
-
-
-
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-
cause.printStackTrace();
-
Channel channel = ctx.channel();
-
// 移除集合
-
channelList.remove(channel);
-
System.out.println("[Server]:" channel.remoteAddress().toString().substring(1) "异常");
-
}
-
}
2、聊天室客户端编写
NettyChatClient
-
package com.lagou.chat;
-
-
import com.lagou.code.MessageCodec;
-
import com.lagou.code.NettyClientHandler;
-
import io.netty.bootstrap.Bootstrap;
-
import io.netty.channel.Channel;
-
import io.netty.channel.ChannelFuture;
-
import io.netty.channel.ChannelInitializer;
-
import io.netty.channel.EventLoopGroup;
-
import io.netty.channel.nio.NioEventLoopGroup;
-
import io.netty.channel.socket.SocketChannel;
-
import io.netty.channel.socket.nio.NioSocketChannel;
-
import io.netty.handler.codec.string.StringDecoder;
-
import io.netty.handler.codec.string.StringEncoder;
-
-
import java.util.Scanner;
-
-
/**
-
* 聊天室客户端
-
*/
-
public class NettyChatClient {
-
private String ip;
-
private int port;
-
-
public NettyChatClient(String ip, int port) {
-
this.ip = ip;
-
this.port = port;
-
}
-
-
public void run() throws InterruptedException {
-
// 1. 创建线程组
-
EventLoopGroup group = null;
-
try {
-
group = new NioEventLoopGroup();
-
// 2. 创建客户端启动助手
-
Bootstrap bootstrap = new Bootstrap();
-
// 3. 设置线程组
-
bootstrap.group(group)
-
.channel(NioSocketChannel.class) // 4. 设置客户端通道实现为NIO
-
.handler(new ChannelInitializer<SocketChannel>() { // 5. 创建一个通道初始化对象
-
-
protected void initChannel(SocketChannel ch) throws Exception {
-
// 6. 向pipeline中添加自定义业务处理handler
-
// 添加编解码器
-
ch.pipeline().addLast(new StringDecoder());
-
ch.pipeline().addLast(new StringEncoder());
-
// 添加客户端的处理类
-
ch.pipeline().addLast(new NettyChatClientHandler());
-
}
-
});
-
// 7. 启动客户端,等待连接服务端,同时将异步改为同步
-
ChannelFuture channelFuture = bootstrap.connect(ip, port).sync();
-
Channel channel = channelFuture.channel();
-
System.out.println("----------" channel.localAddress().toString().substring(1) "-------------");
-
Scanner scanner = new Scanner(System.in);
-
while(scanner.hasNextLine()) {
-
String msg = scanner.nextLine();
-
// 向服务端发送消息
-
channel.writeAndFlush(msg);
-
}
-
// 8. 关闭通道和关闭连接池
-
channelFuture.channel().closeFuture().sync();
-
}finally {
-
group.shutdownGracefully();
-
}
-
}
-
-
public static void main(String[] args) throws InterruptedException {
-
new NettyChatClient("127.0.0.1", 9998).run();
-
}
-
}
NettyChatClientHandler
-
package com.lagou.chat;
-
-
import io.netty.channel.ChannelHandlerContext;
-
import io.netty.channel.SimpleChannelInboundHandler;
-
-
/**
-
* 聊天室处理handler
-
*/
-
public class NettyChatClientHandler extends SimpleChannelInboundHandler<String> {
-
/**
-
* 通道就绪事件
-
* @param ctx
-
* @param msg
-
* @throws Exception
-
*/
-
-
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
-
System.out.println(msg);
-
}
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgakije
系列文章
更多
同类精品
更多
-
第二十二篇Java NIO重点
-
Elasticsearch8 解决启动报错fatal exception while booting Elasticsearchjava.nio.file.InvalidPathException
-
Android 编译jar异常AGPBI: {“kind“:“error“,“text“:“java.nio.file.NoSuchFileException: C:\\Program Files
-
网络通信编程基础,BIO,NIO
-
Java基础:《netty3—NIO:Buffer》
-
java网络和IOBIO/NIO面试题,从Linux底层告诉你为什么Java这么设计----持续补充
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01