1.pom文件添加
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.39.Final</version>
</dependency>
2.服务端处理器
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class SocketHandler extends SimpleChannelInboundHandler<String> {
/**
* 客户端发消息会触发
*/
@Override
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("========================[" + this.getIP(ctx) + "]收到消息:" + msg+"========================");
ClientManager1.getInstance().handleMsg(this.getIP(ctx), "This is response");
}
/**
* 客户端连接会触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//添加channel信息
ClientManager1.getInstance().putChannel(this.getIP(ctx), ctx.channel());
System.out.println("========================[" + this.getIP(ctx) + "]已连接========================");
}
/**
* 客户端断开连接会触发
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//删除失效的channel
ClientManager1.getInstance().removeChannel(getIP(ctx));
ctx.close();
System.out.println("========================[" + this.getIP(ctx) + "]已断开========================");
}
/**
* 发生异常触发
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {
System.out.println("========================[" + this.getIP(ctx) + "]发生异常:" + t+"========================");
ctx.close();
}
/**
* 获取IP地址
*/
private String getIP(ChannelHandlerContext ctx) {
String socketString = ctx.channel().remoteAddress().toString();
int index = socketString.indexOf(":");
String ip = socketString.substring(1, index);
return ip;
}
}
3.服务端
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
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;
/**
*
* @author Administrator
*/
public class Server {
//端口号
private int port;
public Server(int port) {
this.port = port;
}
//启动方法
public void start() throws Exception {
//负责接收客户端的连接的线程。线程数设置为1即可,netty处理链接事件默认为单线程,过度设置反而浪费cpu资源
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
//负责处理数据传输的工作线程。线程数默认为CPU核心数乘以2
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
//在ServerChannelInitializer中初始化ChannelPipeline责任链,并添加到serverBootstrap中
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() { // (6)
@Override
public void initChannel(SocketChannel channel) throws Exception {
//添加编解码
channel.pipeline().addLast("decoder", new StringDecoder());
channel.pipeline().addLast("encoder", new StringEncoder());
// 添加上自己的处理器
channel.pipeline().addLast("socketHandler", new SocketHandler());
}
});//标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度
bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
//是否启用心跳保活机制
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
//将小的数据包包装成更大的帧进行传送,提高网络的负载
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
//绑定端口后,开启监听
ChannelFuture future = bootstrap.bind(port).sync();
//等待服务监听端口关闭
future.channel().closeFuture().sync();
} finally {
//释放资源
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
4.服务端测试代码
//服务端测试代码
public static void main(String[] args) {
try {
int port = 8088;
new Server(port).start();
} catch (Exception e) {
e.printStackTrace();
}
}
5.客户端
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
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;
/**
*
* @author Administrator
*/
public class Client {
//主机名/IP
private String host;
//端口号
private int port;
public Client(String host, int port) {
this.host = host;
this.port = port;
}
//启动方法
public void start() throws Exception {
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast("decoder", new StringDecoder());
channel.pipeline().addLast("encoder", new StringEncoder());
channel.pipeline().addLast(new SimpleChannelInboundHandler<String>(){
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("========================收到服务器消息:" + msg+"========================");
}
});
}
});
//建立连接
ChannelFuture future = bootstrap.connect(host, port).sync();
//发送消息
future.channel().writeAndFlush("This is Request");
//等待服务监听端口关闭
future.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
}
}
6.客户端测试
//客户端测试代码
public static void main(String[] args) {
try {
String host = "192.168.100.38";
int port = 8899;
new Client(host, port).start();
} catch (Exception e) {
e.printStackTrace();
}
}