從入門到超神進(jìn)階的Netty群聊系統(tǒng)
服務(wù)端
服務(wù)端一樣的需要創(chuàng)建BossGroup 和 WorkGroup , 然后使用ServerBootStrap 來配置Netty和啟動Netty。
public class NettyGroupChatServer {
public static void main(String[] args) {
new NettyGroupChatServer().start();
}
//監(jiān)聽
public void start(){
//循環(huán)組
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
//啟動引導(dǎo)
ServerBootstrap bootstrap = new ServerBootstrap();
//Netty配置
bootstrap.group(bossGroup,workGroup)
.option(ChannelOption.SO_BACKLOG,32)
.childOption(ChannelOption.SO_KEEPALIVE,true)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
//解碼器
channel.pipeline().addLast("decoder", new StringDecoder());
//編碼器
channel.pipeline().addLast("encoder",new StringEncoder());
//處理器
channel.pipeline().addLast("nettyGroupChatHandler",new NettyGroupChatServerHandler());
}
});
try {
//啟動服務(wù)
ChannelFuture future = bootstrap.bind(new InetSocketAddress("127.0.0.1", 8888)).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//關(guān)閉資源
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
服務(wù)端處理器我們通過繼承 SimpleChannelInboundHandler 入站Handler來處理消息。
其中提供了幾個方法
- channelRead0 ():讀取消息
- handlerRemoved ():客戶端斷開
- handlerAdded ():客戶端建立連接
- exceptionCaught ():出現(xiàn)異常
具體代碼如下
public class NettyGroupChatServerHandler extends SimpleChannelInboundHandler<String> {
//把所有客戶端的channel保存起來
private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
String message = dateFormat.format(new Date())+":%s:"+msg;
//消息轉(zhuǎn)發(fā)給所有的客戶端
channels.forEach(channel -> {
if(channel == ctx.channel()){
String sendMsg = String.format(message, "我");
channel.writeAndFlush(sendMsg);
System.out.println(sendMsg);
}else{
String sendMsg = String.format(message, ctx.channel().remoteAddress());
channel.writeAndFlush(sendMsg);
System.out.println(sendMsg);
}
});
}
//斷開連接 , 把消息廣播給其他客戶端
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":斷開連接";
channels.writeAndFlush(message);
System.out.println(message);
}
//建立連接
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":加入聊天室";
//自動把消息廣播給其客戶端
channels.writeAndFlush(message);
//客戶端加入組
channels.add(ctx.channel());
System.out.println(message);
}
//出現(xiàn)異常
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.channel().close();
}
//客戶端退出
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":退出聊天室";
System.out.println(message);
}
//客戶端出于活動
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String message = dateFormat.format(new Date())+":"+ctx.channel().remoteAddress()+":上線啦";
System.out.println(message);
}
}
客戶端
客戶端需要創(chuàng)建一個循環(huán)事件組,然后通過BootStrap去啟動,然后掃描鍵盤輸入作為數(shù)據(jù)源來把信息發(fā)送給服務(wù)端
public class NettyGroupChatClient {
public static void main(String[] args) {
new NettyGroupChatClient().start();
}
public void start(){
NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
//解碼器
channel.pipeline().addLast("decoder", new StringDecoder());
//編碼器
channel.pipeline().addLast("encoder",new StringEncoder());
//處理器
channel.pipeline().addLast("nettyGroupChatClientHandler",new NettyGroupChatClientHandler());
}
});
try {
ChannelFuture future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8888)).sync();
//通道
Channel channel = future.channel();
//掃描鍵盤輸入
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextLine()){
String message = scanner.nextLine();
//發(fā)送數(shù)據(jù)
channel.writeAndFlush(message);
}
} catch (InterruptedException e) {
}finally {
eventLoopGroup.shutdownGracefully();
}
}
}
對于處理器只需要接收服務(wù)端轉(zhuǎn)發(fā)過來的消息即可
public class NettyGroupChatClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
}
}
啟動服務(wù)端和多個客戶端,效果如下



到此這篇關(guān)于從入門到超神系列的Netty群聊系統(tǒng)的文章就介紹到這了,更多相關(guān)Netty群聊系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法
本篇文章主要介紹了詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03
使用SSM+Layui+Bootstrap實現(xiàn)汽車維保系統(tǒng)的示例代碼
本文主要實現(xiàn)對汽車維修廠的信息化管理功能,。實現(xiàn)的主要功能包含用戶管理、配置管理、汽車管理、故障管理、供應(yīng)商管理、配件管理、維修訂單管理、統(tǒng)計信息、公告管理、個人信息管理,感興趣的可以了解一下2021-12-12
SpringBoot手動開啟事務(wù):DataSourceTransactionManager問題
這篇文章主要介紹了SpringBoot手動開啟事務(wù):DataSourceTransactionManager問題,具有很好的價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
springboot 使用Spring Boot Actuator監(jiān)控應(yīng)用小結(jié)
本篇文章主要介紹了springboot 使用Spring Boot Actuator監(jiān)控應(yīng)用小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02

