一:定义服务端
定义服务端的启动代码
public static void main(String[] args) throws InterruptedException {
//链接监听组
EventLoopGroup boosLoop = new NioEventLoopGroup(1);
//工作组
EventLoopGroup workerLoop = new NioEventLoopGroup(8);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
//绑定两个线程组
bootstrap.group(boosLoop, workerLoop)
//使用NioSocketChannel来作为通道的服务
.channel(NioServerSocketChannel.class)
//设置线程组队列的最大连接数
.option(ChannelOption.SO_BACKLOG,128)
//设置保存活动链接状态
.childOption(ChannelOption.SO_KEEPALIVE,true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//在pipeline链路中添加解码编码器
socketChannel.pipeline().addLast("decoder",new StringDecoder());
socketChannel.pipeline().addLast("encoder",new StringEncoder());
//在ChannelPipeline 中添加自定义的处理函数
socketChannel.pipeline().addLast(new MyNettyServerHandler());
}
});
System.out.println("服务端端已经启动成功。。。。");
ChannelFuture sync = bootstrap.bind(6666).sync();
sync.channel().closeFuture().sync();
}finally {
//关闭
boosLoop.shutdownGracefully();
workerLoop.shutdownGracefully();
}
}
定义自定义的handler
public class MyNettyServerHandler extends SimpleChannelInboundHandler<String> {
/**
* 定义一个channel组 用于管理所有注入的channel
* GlobalEventExecutor.INSTANCE 是一个全局事件执行器 是一个单例
*/
private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
//通知族群中的其他channel
channelGroup.writeAndFlush("【客户端】"+channel.remoteAddress() + "加入聊天室");
//并把当前channel加入到族群中
channelGroup.add(ctx.channel());
}
/**
* 断开连接的时候调用
*/
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
//通知族群中的其他channel
channelGroup.writeAndFlush("【客户端】"+channel.remoteAddress() + "离开聊天室");
}
/**
* 处于活跃状态调用
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("【客户端】"+ctx.channel().remoteAddress() + "上线");
}
/**
* 处于非活跃状态
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("【客户端】"+ctx.channel().remoteAddress() + "下线");
}
/**
* 读取客户端发来的数据 并进行转发
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
String s = "【客户端】"+ctx.channel().remoteAddress() + "说:" + msg;
channelGroup.forEach(i->{
//进行转发
if (i != ctx.channel()){
i.writeAndFlush(s);
}
});
}
/**
* 发生异常的时候调用
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("【客户端】"+ctx.channel().remoteAddress() + "发生异常");
ctx.channel();
}
}
二:定义客户端
定义客户端的启动代码
public static void main(String[] args) throws InterruptedException {
//客户端只需要定义一个工作线程组就可以
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap serverBootstrap = new Bootstrap();
serverBootstrap.group(workerGroup)
//使用NioSocketChannel来作为通道的服务
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//在pipeline链路中添加解码编码器
socketChannel.pipeline().addLast("decoder",new StringDecoder());
socketChannel.pipeline().addLast("encoder",new StringEncoder());
//在ChannelPipeline 中添加自定义的处理函数
socketChannel.pipeline().addLast(new MyNettyClientHandler());
}
});
ChannelFuture sync = serverBootstrap.connect("127.0.0.1", 6666).sync();
Channel channel = sync.channel();
System.out.println(">>>>"+channel.remoteAddress()+">>>>>>");
//定义一个输入器 进行输入
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()){
channel.writeAndFlush(scanner.nextLine() );
}
}finally {
//关闭
workerGroup.shutdownGracefully();
}
}
定义自己的处理器 handler
public class MyNettyClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
}
}
二:测试