文章目录
- 一、前言介绍
- 二、代码实现
- 2.1 工程结构
- 2.2 Netty服务端字符串解码器实现
- 2.2.1 服务端处理器
- 2.2.2 通道初始化
- 2.2.3 netty服务端
- 2.3 单元测试
一、前言介绍
💡 服务端接收数据后我们希望是一个字符串或者是一个对象类型,而不是字节码。
- 在
netty
中是否可以自动的把接收的Bytebuf
数据转为String
,不需要手动处理?- 答:可以在管道中添加一个
StringDecoder
。
- 答:可以在管道中添加一个
- 在网络传输过程中有半包粘包的问题,
netty
能解决吗?- 答:netty 提供了很丰富的解码器,在正确合理的使用下就能解决半包粘包问题。
- 常用的
String
字符串下有什么样的解码器呢?- 答:不仅在
String
下有处理半包粘包的解码器在处理其他的数据格式也有,其中谷歌的protobuf
数据格式就是其中一个。对于String
的有以下常用的三种:LineBasedFrameDecoder
:基于换行。DelimiterBasedFrameDecoder
:基于指定字符串。FixedLengthFrameDecoder
:基于字符串长度。
- 答:不仅在
二、代码实现
2.1 工程结构
netty-1.0-04
|-src
|-main
|-java
|-com.lino.netty.server
|-MyChannelInitializer.java
|-MyServerHandler.java
|-NettyServer.java
2.2 Netty服务端字符串解码器实现
2.2.1 服务端处理器
MyServerHandler.java
package com.lino.netty.server;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @description: 服务端处理器
*/
public class MyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
SocketChannel channel = (SocketChannel) ctx.channel();
System.out.println("链接报告开始");
System.out.println("链接报告信息:有一客户端链接到本服务端");
System.out.println("链接报告IP:" + channel.localAddress().getHostString());
System.out.println("链接报告Port:" + channel.localAddress().getPort());
System.out.println("链接报告完毕");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 接收msg消息
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);
}
}
2.2.2 通道初始化
MyChannelInitializer.java
package com.lino.netty.server;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import java.nio.charset.Charset;
/**
* @description: 通道初始化
*/
public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) {
// 解码转String,注意调整自己的编码格式 GBK,UTF-8
channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
// 在管道中添加接收数据实现方法
channel.pipeline().addLast(new MyServerHandler());
}
}
- 添加接收数据实现方法。
2.2.3 netty服务端
NettyServer.java
package com.lino.netty.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @description: netty服务端
*/
public class NettyServer {
public static void main(String[] args) {
new NettyServer().bind(7397);
}
/**
* 开启链接
*
* @param port 端口
*/
private void bind(int port) {
// 配置服务端NIO线程组
// NioEventLoopGroup extends MultithreadEventLoopGroup
// Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(parentGroup, childGroup)
// 非阻塞模式
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childHandler(new MyChannelInitializer());
ChannelFuture future = b.bind(port).sync();
System.out.println("lino-learn-netty server start done.");
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
childGroup.shutdownGracefully();
parentGroup.shutdownGracefully();
}
}
}
2.3 单元测试
启动NettyServer
链接报告开始
链接报告信息:有一客户端链接到本服务端
链接报告IP:127.0.0.1
链接报告Port:7397
链接报告完毕
2023-02-17 19:36:39 接收到消息:你好,netty服务端!
2023-02-17 19:36:40 接收到消息:你好,netty服务端!
2023-02-17 19:36:40 接收到消息:你好,netty服务端!
网络调试助手