需求:
大概流程:
- 编写服务端
- 编写服务端handler
- 编写客户端
- 编写客户端handler
服务端开发:
server:
package com.example.demo.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;
import org.apache.catalina.Pipeline;
public class chatServer {
public int port;
public chatServer(int port){
this.port=port;
}
public void run () throws Exception {
EventLoopGroup workGroup= new NioEventLoopGroup();
EventLoopGroup boosGroup=new NioEventLoopGroup();
try{
ServerBootstrap bootstrap=new ServerBootstrap();
bootstrap.group(boosGroup,workGroup)
.channel(NioServerSocketChannel.class)//使用NioServerSocketChannel,作为服务器的通道实现
.option(ChannelOption.SO_BACKLOG,128)//设置线程队列的连接个数
.childOption(ChannelOption.SO_KEEPALIVE,true)//设置保持活动连接状态
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline=socketChannel.pipeline();
//解码器
pipeline.addLast("decode", new StringDecoder());
//编码器
pipeline.addLast("encode",new StringEncoder());
//自定义处理
pipeline.addLast("myHandler",new chatServerHandler());
}
});
ChannelFuture future=bootstrap.bind(this.port).sync();
future.channel().closeFuture().sync();
}finally {
workGroup.shutdownGracefully();;
boosGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new chatServer(6668).run();
}
}
serverHandler:
package com.example.demo.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.text.SimpleDateFormat;
import java.util.Date;
public class chatServerHandler extends SimpleChannelInboundHandler {
//定义一个channel组,管理所有的channel
private static ChannelGroup channelGroup=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
private static SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//一旦连接就会执行的函数
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel=ctx.channel();
channelGroup.add(channel);
//给房间中的人发送消息
channelGroup.writeAndFlush("客户端"+channel.remoteAddress()+"加入了聊天室,时间"+format.format(new Date()));
}
//断开连接触发函数
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
Channel channel=ctx.channel();
channelGroup.remove(channel);
channelGroup.writeAndFlush("客户端"+channel.remoteAddress()+"退出了房间,时间:"+format.format(new Date()));
System.out.println("当前人数:"+channelGroup.size());
}
@Override
protected void messageReceived(ChannelHandlerContext ctx, Object o) throws Exception {
//获取到当前的channel
Channel channel=ctx.channel();
//遍历group,根据不同情况回送不同的数据
for (Channel ch : channelGroup) {
if(channel!=ch){
ch.writeAndFlush("客户"+channel.remoteAddress()+"发送了一条消息:"+o);
}else{
channel.writeAndFlush("我给自己发送了一条消息"+o);
}
}
}
}
客户端开发:
package com.example.demo.chat;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
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 client {
private String host;
private int port;
public client(String host,int port){
this.host=host;
this.port=port;
}
public void run() throws Exception {
EventLoopGroup group=new NioEventLoopGroup();
try{
Bootstrap bootstrap=new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>()
{
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline=socketChannel.pipeline();
pipeline.addLast("decode",new StringDecoder());
pipeline.addLast("encode", new StringEncoder());
pipeline.addLast("myHandler",new clientHandler());
}
});
//读取数据,发送数据
ChannelFuture future=bootstrap.connect(this.host,this.port).sync();
Scanner scanner=new Scanner(System.in);
Channel channel=future.channel();
while(scanner.hasNextLine()){
String msg=scanner.nextLine();
channel.writeAndFlush(msg);
}
}finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new client("127.0.0.1",6668).run();
}
}
客户端handler:
public class clientHandler extends SimpleChannelInboundHandler {
@Override
protected void messageReceived(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
System.out.println("客户接受到了一条消息----"+o);
}
}