hadler往往決定了服務的類型
一、server端
import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * 服務端 * 是什麼服務是childHandler決定即MyServerInitializer決定 */ public class MyServer { public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).childHandler(new MyServerInitializer()); ChannelFuture channelFuture = serverBootstrap.bind(8888).sync(); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
ChannelInitializer channel初始化
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; public class MyServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); //加入handler決定服務器的類型 pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4)); pipeline.addLast(new LengthFieldPrepender(4)); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast(new MyServerHandler()); } }
handler的泛型決定了,消息的類型
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import java.util.UUID; public class MyServerHandler extends SimpleChannelInboundHandler<String> { /** * 必須客戶端發起請求時纔會觸發 * extends SimpleChannelInboundHandler<String>的泛型String和參數s的類型是一樣的 * @param channelHandlerContext 通過它可以獲取連接信息,給客戶端發送信息 * @param msg 就是接受客戶端的消息 * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception { System.out.println(channelHandlerContext.channel().remoteAddress() + ". \t"+ msg); channelHandlerContext.channel().writeAndFlush("from server msg " + UUID.randomUUID()); } @Override public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception{ cause.printStackTrace(); ctx.close(); } }
客戶端(一樣的套路)
import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; public class MyClient { public static void main(String[] args) { EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new MyClientInitializer()); ChannelFuture channelFuture = bootstrap.connect("localhost", 8888).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { eventLoopGroup.shutdownGracefully(); } } }
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; public class MyClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); //加入handler決定了服務的類型 pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4)); pipeline.addLast(new LengthFieldPrepender(4)); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); //自定義hanlder pipeline.addLast(new MyClientHandler()); } }
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import java.time.LocalDateTime; public class MyClientHandler extends SimpleChannelInboundHandler<String> { /** * 必須服務端發起請求數據,纔會觸發 * 客戶端與服務端通信的地方 * @param channelHandlerContext * @param msg * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception { System.out.println(channelHandlerContext.channel().remoteAddress()); System.out.println("client receive:" + msg); //給服務端發消息 channelHandlerContext.writeAndFlush("from client:" + LocalDateTime.now()); } /** * * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception{ //沒有此句,服務端和客戶端都收不到消息 ctx.writeAndFlush("來自於客戶端的問候,我激活的客戶端與服務端通信"); } }
三、通過端口查看現象