5. Netty初认识--入门应用-客户端和服务端交互不断输出内容
SomeServer
.java
package club.wujingjian.study;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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;
public class SomeServer {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup parentGroup = new NioEventLoopGroup();
NioEventLoopGroup childGroup = new NioEventLoopGroup();
try{
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(parentGroup,childGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//StringDecoder()字符串解码器,将Channel中的ByteBuf数据解码为String
//StringEncoder()字符串编码器,将要写入Channel中的String编码为ByteBuf
ch.pipeline().addLast(new StringEncoder()).addLast(new StringDecoder())
.addLast(new SomeServerHandler());
}
});
ChannelFuture future = bootstrap.bind(8888).sync();
System.out.println("服务器已启动");
future.channel().closeFuture().sync();
}finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
SomeServerHandler
.java
package club.wujingjian.study;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class SomeServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//将来自于客户端的数据打印
System.out.println(ctx.channel().remoteAddress() + ", " + msg);
//向客户端发送数据
ctx.channel().writeAndFlush("from server:这里是服务器的响应数据!" + UUID.randomUUID());
TimeUnit.MICROSECONDS.sleep(500);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
SomeClient
.java
package club.wujingjian.study.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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;
public class SomeClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder())
.addLast(new StringDecoder())
.addLast(new SomeClientHandler());
}
});
ChannelFuture future = bootstrap.connect("localhost", 8888).sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
SomeClientHandler
.java
package club.wujingjian.study.client;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
public class SomeClientHandler extends SimpleChannelInboundHandler<String> {
// msg的消息类型与类中的泛型类型是一致的
//SimpleChannelInboundHandler 中的ChannelRead()方法会自动释放接收到的来自于对方的msg所占有的所有资源.
//ChannelInboundHandlerAdapter中的ChannelRead()方法不会自动释放接收到的来自于对方的msg所占有的所有资源.
//以下两种情况建议使用ChannelInboundHandlerAdapter,
/**
* 第一种情况:
* 若对方没有向自己发送数据,则自定义处理器建议继承自ChannelInboundHandlerAdapter,因为若继承自SimpleChannelInboundHandler需要
* 重写channelRead0()方法,而重写该方法的目的是对来自于对方的数据进行处理.因为对方没发送数据,所以没必要重写channelRead0().
*/
/**
* 第二种情况:
* 若对方向自己发送数据,而自己又需要将该数据再发送给对方,则自定义处理器建议继承自ChannelInboundHandlerAdapter.因为write()方法的
* 执行是异步的,且SimpleChannelInboundHandler中的channelRead()方法会自动释放掉来自于对方的msg.若write()方法中正在处理msg,而此时
* SimpleChannelInboundHandler中的channelread()方法执行完毕了,将msg给释放了,此时就会报错.
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("from server:来自于服务端" +ctx.channel().remoteAddress()+ " 的消息:" + msg);
ctx.writeAndFlush("来自于客户端的消息:" + LocalDateTime.now());
TimeUnit.MICROSECONDS.sleep(500);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("客户端异常" + ctx.close() );
}
//当Channel被激活会触发该方法的执行
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush("1.from client: 客户端的channel被激活了,begin talking");
}
}
服务端输出:
客户端输出:
标题:5. Netty初认识--入门应用-客户端和服务端交互不断输出内容
作者:码农路上
地址:http://wujingjian.club/articles/2020/02/28/1582883899662.html