import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
public class NettyServer {
public static void main(String[] args) {
EventLoopGroup bossGroup=new NioEventLoopGroup();
EventLoopGroup workerGroup=new NioEventLoopGroup();
ChannelFuture channelFuture = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
// 指定连接数据读写逻辑
ch.pipeline().addLast(new MyServerHandler());
}
}).bind(9999);
channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
if (future.isSuccess()) {
System.out.println("端口绑定成功!");
} else {
System.err.println("端口绑定失败!");
}
}
});
}
}
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.nio.charset.Charset;
public class MyServerHandler extends ChannelInboundHandlerAdapter {
//收到数据之后调用
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf byteBuf = (ByteBuf) msg;
System.out.println("服务端读到数据:" + byteBuf.toString(Charset.forName("utf-8")));
System.out.println("服务端写出数据");
ByteBuf buffer=ctx.alloc().buffer();
buffer.writeBytes("ready".getBytes(Charset.forName("utf-8")));
ctx.writeAndFlush(buffer);
}
}
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import java.net.InetSocketAddress;
public class NettyClient {
public static void main(String[] args) {
EventLoopGroup client = new NioEventLoopGroup();
ChannelFuture channelFuture = new Bootstrap()
.group(client)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 指定连接数据读写逻辑
pipeline.addLast(new MyClientHandler());
}
})
.connect(new InetSocketAddress("127.0.0.1", 9999));
channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
if (future.isSuccess()) {
System.out.println("连接成功");
} else {
System.out.println("连接失败");
}
}
});
}
}
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.nio.charset.Charset;
/**
* 向服务端写数据的处理器
*/
public class MyClientHandler extends ChannelInboundHandlerAdapter {
//在客户端连接建立成功之后被调用
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("服务端写出数据");
// 1. 准备数据
// 1.1 获取二进制抽象 ByteBuf
ByteBuf buffer = ctx.alloc().buffer();
// 1.2 指定字符串的字符集为 utf-8
byte[] bytes = "hello server!".getBytes(Charset.forName("utf-8"));
// 1.3 填充数据到 ByteBuf
buffer.writeBytes(bytes);
// 2. 写数据并发送
ctx.channel().writeAndFlush(buffer);
}
//收到数据之后调用
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf= (ByteBuf) msg;
System.out.println("客户端读到数据:"+byteBuf.toString(Charset.forName("utf-8")));
//给连接设置属性,如登录成功标识等
//ctx.channel().attr(CLIENT_FLAG).set(true);
}
}
- 客户端和服务端的逻辑处理均是在启动的时候(childHandler或handler方法中),通过给逻辑处理链
pipeline
添加逻辑处理器,来编写数据的读写逻辑 - 在客户端连接成功之后会回调到逻辑处理器的
channelActive()
方法,而不管是服务端还是客户端,收到数据之后都会调用到 channelRead
方法 - 写数据调用ctx.channel().writeAndFlush()方法,客户端与服务端交互的二进制数据载体为
ByteBuf
,ByteBuf
通过连接的内存管理器创建,字节数据填充到 ByteBuf
之后才能写到对端(buffer.writeBytes(bytes))