Encoder: Handles outbound data and converts message objects into byte arrays.
Decoder: Handles inbound data and converts byte arrays into message objects.
Note: Since the actual transmission in the network channel is a binary sequence of bytes, for outbound data, the last OutboundHandler to process the data must send data in type ByteBuf.
Similarly, for an inbound message, the first InboundHandler to receive the message must receive data of type ByteBuf.
There are two Handler chains in the Pipline of a Channel, the OutboundHandler chain for the outbound data and the InboundHandler chain for the inbound data. head —–>tail
Pipeline ().addlast () is added at the end, and pipeline().addfirst () is added at the head.
Netty provides many codecs out of the box:
StringEncoder
String encoderStringDecoder
String decoderObjectEncoder
Object encoderObjectDecoder
Object decoderFixedLengthFrameDecoder
Fixed length decoderLineBasedFrameDecoder
A decoder that ends with a newline characterDelimiterBasedFrameDecoder
Specifies a decoder for message separatorsLengthFieldBasedFrameDecoder
Length based universal decoder
The code field
We use Netty to implement an Echo server that only receives messages from the client and returns them to the client.
Introduction of depend on
Ty < dependency > < groupId > io.net < / groupId > < artifactId > netty -all < / artifactId > < version > 4.1.50. The Final < / version > </dependency>Copy the code
The service side EhcoServer
public class Server {
public void start(a) {
NioEventLoopGroup boss = new NioEventLoopGroup(1);
NioEventLoopGroup worker = new NioEventLoopGroup(1);
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker)
.localAddress(9999)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(newEchoInboundHandler()); }}); ChannelFuture future =null;
try {
future = bootstrap.bind().sync();
System.out.println("Server started successfully, listening port:" + future.channel().localAddress());
// Wait for the server listening port to close
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// Close gracefullyboss.shutdownGracefully(); worker.shutdownGracefully(); }}public static void main(String[] args) {
newServer().start(); }}Copy the code
public class EchoInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf byteBuf = (ByteBuf) msg; ctx.writeAndFlush(byteBuf); }}Copy the code
The client
public class Client {
Bootstrap bootstrap = new Bootstrap();
public Client(a){
NioEventLoopGroup worker = new NioEventLoopGroup();
bootstrap.group(worker)
.channel(NioSocketChannel.class)
.remoteAddress("127.0.0.1".9999);
}
public void send(String msg){
try {
Channel channel = bootstrap.connect().sync().channel();
System.out.println("Client sends message:" + msg);
channel.writeAndFlush(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
} catch (InterruptedException e) {
e.printStackTrace();
}finally{}}}Copy the code
CASE1 does not use any encoder to send messages
public void send(String msg){
try {
Channel channel = bootstrap.connect().sync().channel();
System.out.println("Client sends message:" + msg);
channel.writeAndFlush(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
} catch (InterruptedException e) {
e.printStackTrace();
}finally{}}Copy the code
Without using an encoder, you need to manually convert the message to ByteBuf when sending the message, such as Unpooled. CopiedBuffer (MSG, charsetutil.utf_8)
CASE2 useStringEncoder
public void send(String msg){
try {
Channel channel = bootstrap.connect().sync().channel();
channel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
System.out.println("Client sends message:" + msg);
channel.writeAndFlush(msg);
} catch(InterruptedException e) { e.printStackTrace(); }}Copy the code
Through the channel. Pipeline (.) addLast (new StringEncoder (CharsetUtil. UTF_8)); When you add a String encoder, you can send String data directly.
channel.writeAndFlush(msg);
CASE3 custom encoder
Convert the entity class Person to Json and send it
@Data
public class Person {
private String name;
private int age;
}
Copy the code
inheritanceMessageToMessageEncoder
public class JsonEncoder extends MessageToMessageEncoder<Person> {
@Override
protected void encode(ChannelHandlerContext ctx, Person person, List<Object> out) throws Exception {
byte[] bytes = JSON.toJSONBytes(person); ByteBuf byteBuf = Unpooled.buffer(bytes.length); byteBuf.writeBytes(bytes); out.add(byteBuf); }}Copy the code
Send an entity-class message
public void send(Person person){
try {
Channel channel = bootstrap.connect().sync().channel();
channel.pipeline().addLast(new JsonEncoder());
channel.writeAndFlush(person);
} catch(InterruptedException e) { e.printStackTrace(); }}Copy the code