客户端:
public class MyClient {
public static void main(String[] args) throws Exception{
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class)
.handler(new MyClientInitializer()); //自定义一个初始化类
ChannelFuture channelFuture = bootstrap.connect("localhost", 7000).sync();
channelFuture.channel().closeFuture().sync();
}finally {
group.shutdownGracefully();
}
}
}
public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//加入一个出站的handler 对数据进行一个编码
pipeline.addLast(new MyLongToByteEncoder());
//这时一个入站的解码器(入站handler )
//pipeline.addLast(new MyByteToLongDecoder());
pipeline.addLast(new MyByteToLongDecoder2());
//加入一个自定义的handler , 处理业务
pipeline.addLast(new MyClientHandler());
}
}
写编码器,已经是long不需要编码
public class MyLongToByteEncoder extends MessageToByteEncoder<Long> {
//编码方法
@Override
protected void encode(ChannelHandlerContext ctx, Long msg, ByteBuf out) throws Exception {
System.out.println("MyLongToByteEncoder encode 被调用");
System.out.println("msg=" + msg);
out.writeLong(msg);
}
}
客户端发数据:
writeAndFlush之后先走的是
----
测试:
完成功能,客户端编码,服务器解吗。
启动服务器端:
1.服务器加解码器
2.
启动客户端:
客户端的调用顺序:
1.handler就是监听到读取或者发送事件之后做的事情。
2.
------------------------------------------------------------81--------------------------------------------------------------------
细节问题:
我们在客户端发送这么一段代码,这个是16个字节:
此时按照服务器读取的方式,我们看会调用几次?
decode方法会根据接受到的数据被调用多次,直到确定没有新的元素被添加到list,或者bytebuf没有更多的可读字节为止。
----------------------------------------------------------
客户端本来是要调用LongToByte编码器的,但是发送字符串就没有调用编码器了。
其父类,我们看write方法
核心代码:
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
ByteBuf buf = null;
try {
if (acceptOutboundMessage(msg)) { // 当前的msg是不是我要处理的 不是就逃过
@SuppressWarnings("unchecked")
I cast = (I) msg;
buf = allocateBuffer(ctx, cast, preferDirect);
try {
encode(ctx, cast, buf);
} finally {
ReferenceCountUtil.release(cast);
}
if (buf.isReadable()) {
ctx.write(buf, promise);
} else {
buf.release();
ctx.write(Unpooled.EMPTY_BUFFER, promise);
}
buf = null;
} else {
ctx.write(msg, promise);
}
} catch (EncoderException e) {
throw e;
} catch (Throwable e) {
throw new EncoderException(e);
} finally {
if (buf != null) {
buf.release();
}
}
}
我们写的泛型是long是不匹配的。
解决:注意什么是编码什么是解码。
------------------------------------------------------------82--------------------------------------------------------------------
服务端的编写:
编写代码:先写服务器端口
第一步:
public class MyServerHandler extends SimpleChannelInboundHandler<Long> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Long msg) throws Exception {
System.out.println("从客户端" + ctx.channel().remoteAddress() + " 读取到long " + msg);
//给客户端发送一个long
ctx.writeAndFlush(98765L);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
第二步:加入编码器
public class MyLongToByteEncoder extends MessageToByteEncoder<Long> {
//编码方法
@Override
protected void encode(ChannelHandlerContext ctx, Long msg, ByteBuf out) throws Exception {
System.out.println("MyLongToByteEncoder encode 被调用");
System.out.println("msg=" + msg);
out.writeLong(msg);
}
}
第三步:客户端拿取信息
public class MyClientHandler extends SimpleChannelInboundHandler<Long> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Long msg) throws Exception {
System.out.println("服务器的ip=" + ctx.channel().remoteAddress());
System.out.println("收到服务器消息=" + msg);
}
测试:
要是这的话:
收到两次
其他客户端:
服务端:
总结:
------------------------------------------------------------83--------------------------------------------------------------------
其他的常用编码器:
改写解码:
public class MyByteToLongDecoder2 extends ReplayingDecoder<Void> {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
System.out.println("MyByteToLongDecoder2 被调用");
//在 ReplayingDecoder 不需要判断数据是否足够读取,内部会进行处理判断
out.add(in.readLong());
}
}
-----------------------------------------------------------84--------------------------------------------------------------------
netty整合Log4j。
第一步:加入依赖
第二步:
------------------------------------------------------------85--------------------------------------------------------------------
总结:链是一条用inbound和outbound区分的。
------------------------------------------------------------86--------------------------------------------------------------------