從入門到超神進(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)文章
如何使用 IntelliJ IDEA 編寫 Spark 應(yīng)用程序(Sc
本教程展示了如何在IntelliJIDEA中使用Maven編寫和運(yùn)行一個簡單的Spark應(yīng)用程序(例如WordCount程序),本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-11-11
Mybatis傳遞多個參數(shù)的三種實現(xiàn)方法
這篇文章主要介紹了Mybatis傳遞多個參數(shù)的三種實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04
Intellij IDEA 最全超實用快捷鍵整理(長期更新)
這篇文章主要介紹了Intellij IDEA 最全實用快捷鍵整理(長期更新),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
idea tomcat亂碼問題的解決及相關(guān)設(shè)置的步驟
這篇文章主要介紹了idea tomcat亂碼問題的解決及相關(guān)設(shè)置的步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

