package com.chigo.it.netty.chat;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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;
/**
* @description:
* @version: 1.0
*/
public class GroupChatServer implements Runnable{
public static void main(String[] args) {
new GroupChatServer().run();
}
@Override
public void run() {
NioEventLoopGroup bossGroup =new NioEventLoopGroup();
NioEventLoopGroup workGroup =new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap =new ServerBootstrap().group(bossGroup,workGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG,128)
.childOption(ChannelOption.SO_KEEPALIVE,true).childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel)throws Exception {
socketChannel.pipeline().addLast("decoder",new StringDecoder());
socketChannel.pipeline().addLast("encoder",new StringEncoder());
socketChannel.pipeline().addLast("serverHandler",new GroupChatServerHandler());
}
});
System.out.println("服务器启动了....");
ChannelFuture channelFuture =serverBootstrap.bind(9999).sync();
channelFuture.channel().closeFuture().sync();
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
package com.chigo.it.netty.chat;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @description:
* @version: 1.0
*/
public class GroupChatServerHandler extends SimpleChannelInboundHandler {
//全局事件执行器
private static final ChannelGroup channelGroup =new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
String format =LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd:hh:mm:ss"));
//连接建立,第一个搪行
@Override
public void handlerAdded(ChannelHandlerContext ctx)throws Exception {
String format =LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd:hh:mm:ss"));
Channel channel = ctx.channel();
channelGroup.writeAndFlush("[客户端]" +channel.remoteAddress() +" " +format +" 加入聊天");
channelGroup.add(channel);
}
//读取信息
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext,String s)throws Exception {
channelGroup.forEach(channel -> {
if (channel !=channelHandlerContext.channel()) {
channel.writeAndFlush("[客户端]" +channelHandlerContext.channel().remoteAddress() +" " +format +"发送了消息=>" +s +"\n");
}else {
channel.writeAndFlush("[自己]发送了消息=>" +s);
}
});
}
//channel处于活动状态,提示上线
@Override
public void channelActive(ChannelHandlerContext ctx)throws Exception {
//channelGroup.writeAndFlush("[客户端]" + ctx.channel().remoteAddress() + " " + format + "=>上线了");
System.out.println("[客户端]" + ctx.channel().remoteAddress() +" " +format +"=>上线了");
}
//channel处于不活动状态,提示离线了
@Override
public void channelInactive(ChannelHandlerContext ctx)throws Exception {
//channelGroup.writeAndFlush("[客户端]" + ctx.channel().remoteAddress() + " " + format + "=>离线了");
System.out.println("[客户端]" + ctx.channel().remoteAddress() +" " +format +"=>离线了");
}
//断开连接,将客户离开信息推送给当前在线的客户
@Override
public void handlerRemoved(ChannelHandlerContext ctx)throws Exception {
Channel channel = ctx.channel();
channelGroup.writeAndFlush("[客户端]" +channel.remoteAddress() +" " +format +"=>离开了");
System.out.println("channelGroup size :" +channelGroup.size());
channelGroup.remove(channel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause)throws Exception {
ctx.channel().close();
}
}
package com.chigo.it.netty.chat;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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;
/**
* @description:
* @version: 1.0
*/
public class GroupChatClient implements Runnable{
public static void main(String[] args) {
new GroupChatClient().run();
}
@Override
public void run() {
NioEventLoopGroup workGroup =new NioEventLoopGroup();
try {
Bootstrap bootstrap =new Bootstrap().group(workGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE,true)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel)throws Exception {
socketChannel.pipeline().addLast("decoder",new StringDecoder());
socketChannel.pipeline().addLast("encoder",new StringEncoder());
socketChannel.pipeline().addLast("clientHandler",new GroupChatClientHandler());
}
});
ChannelFuture channelFuture =bootstrap.connect("localhost",9999).sync();
System.out.println(channelFuture.channel().remoteAddress()+":客户端准备好了...");
Scanner scanner =new Scanner(System.in);
while (scanner.hasNext()) {
String message =scanner.nextLine();
channelFuture.channel().writeAndFlush(message);
}
//channelFuture.channel().closeFuture().sync();
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
workGroup.shutdownGracefully();
}
}
}
package com.chigo.it.netty.chat;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* @description:
* @version: 1.0
*/
public class GroupChatClientHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext,String s)throws Exception {
System.out.println(s.trim());
}
}