阅读本文建议从第一篇开始往后看
本系列文章
- Netty在Android开发中的应用实战系列(一)——— 搭建服务端与客户端
- Netty在Android开发中的应用实战系列(二)——— Encoder | Decoder | Handler 的使用
- Netty在Android开发中的应用实战系列(三)——— 心跳处理 | 断线重连
- Netty在Android开发中的应用实战系列(四)——— 粘包 | 拆包 处理
- Netty在Android开发中的应用实战系列(五)——— 创建Web服务 | 作为HTTP服务器
一、简单的介绍一下Netty
- 官网地址:https://netty.io
- 官网Jar包下载:https://netty.io/downloads.html
- Jar包也可以去mvnrepository下载:https://mvnrepository.com/artifact/io.netty/netty-all
- 直接上官网的介绍再好不过了
- 谷歌翻译过来就是
Netty是一个异步事件驱动的网络应用程序框架用于快速开发可维护的高性能协议服务器和客户端。
- Netty是一个NIO异步非阻塞应用程序框架,关于
IO
、NIO
、AIO
的理解大家可以找文章看看
二、创建Tcp服务端
-
引入
netty-all-4.1.39.Final.jar
-
添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
-
创建
NettyServer.java
开启tcp服务
public class NettyServer {
private static final String TAG = "NettyServer";
//端口
private static final int PORT = 7010;
/**
* 启动tcp服务端
*/
public void startServer() {
try {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//添加发送数据编码器
pipeline.addLast(new ServerEncoder());
//添加解码器,对收到的数据进行解码
pipeline.addLast(new ServerDecoder());
//添加数据处理
pipeline.addLast(new ServerHandler());
}
});
//服务器启动辅助类配置完成后,调用 bind 方法绑定监听端口,调用 sync 方法同步等待绑定操作完成
b.bind(PORT).sync();
Log.d(TAG, "TCP 服务启动成功 PORT = " + PORT);
} catch (Exception e) {
e.printStackTrace();
}
}
}
ServerEncoder.java
服务端发送数据编码器
public class ServerEncoder extends MessageToByteEncoder<Object> {
private static final String TAG = "ServerEncoder";
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Object data, ByteBuf byteBuf) throws Exception {
//自己发送过来的东西进行编码
byteBuf.writeBytes(data.toString().getBytes());
}
}
ServerDecoder.java
解码器,对客户端的数据进行解析
public class ServerDecoder extends ByteToMessageDecoder {
private static final String TAG = "ServerDecoder";
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
//收到的数据长度
int length = byteBuf.readableBytes();
//创建个byteBuf存储数据,进行编辑
ByteBuf dataBuf = Unpooled.buffer(length);
//写入收到的数据
dataBuf.writeBytes(byteBuf);
//将byteBuf转为数组
String data = new String(dataBuf.array());
Log.d(TAG, "收到了客户端发送的数据:" + data);
//将数据传递给下一个Handler,也就是在NettyServer给ChannelPipeline添加的处理器
list.add(data);
}
}
ServerHandler.java
数据处理器
public class ServerHandler extends SimpleChannelInboundHandler<Object> {
private static final String TAG = "ServerHandler";
/**
* 当收到数据的回调
*
* @param channelHandlerContext 封装的连接对像
* @param o
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
Log.d(TAG, "收到了解码器处理过的数据:" + o.toString());
}
/**
* 有客户端连接过来的回调
*
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
Log.d(TAG, "有客户端连接过来:" + ctx.toString());
}
/**
* 有客户端断开了连接的回调
*
* @param ctx
* @throws Exception
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
Log.d(TAG, "有客户端断开了连接:" + ctx.toString());
}
}
- 重点:设置
childHandler(ChannelHandler childHandler)
,对连接通道设置数据处理器(ChannelHandler) - 上面添加了一个数据解码处理器,一个数据处理器,对收到的客户端数据进行处理,如下图所示:
三、创建客户端,与创建服务端差不多一至
- 创建
NettyClient.java
public class NettyClient {
private static final String TAG = "NettyClient";
private final int PORT = 7010;
//连接的服务端ip地址
private final String IP = "192.168.3.111";
private static NettyClient nettyClient;
//与服务端的连接通道
private Channel channel;
public static NettyClient getInstance() {
if (nettyClient == null) {
nettyClient = new NettyClient();
}
return nettyClient;
}
/**
*需要在子线程中发起连接
*/
private NettyClient() {
new Thread(new Runnable() {
@Override
public void run() {
connect();
}
}).start();
}
/**
* 获取与服务端的连接
*/
public static Channel getChannel() {
if (nettyClient == null) {
return null;
}
return nettyClient.channel;
}
/**
* 连接服务端
*/
public void connect() {
try {
NioEventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap()
// 指定channel类型
.channel(NioSocketChannel.class)
// 指定EventLoopGroup
.group(group)
// 指定Handler
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//添加发送数据编码器
pipeline.addLast(new ClientEncoder());
//添加数据处理器
pipeline.addLast(new ClientHandler());
}
});
// 连接到服务端
ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress(IP, PORT));
//获取连接通道
channel = channelFuture.sync().channel();
} catch (Exception e) {
Log.e(TAG, "连接失败:" + e.getMessage());
e.printStackTrace();
}
}
}
ClientEncoder.java
对发送的数据进行编码
public class ClientEncoder extends MessageToByteEncoder<Object> {
private static final String TAG = "ClientEncoder";
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Object data, ByteBuf byteBuf) throws Exception {
//自己发送过来的东西进行编码
byteBuf.writeBytes(data.toString().getBytes());
}
}
ClientHandler.java
数据处理器
public class ClientHandler extends SimpleChannelInboundHandler<Object> {
private static final String TAG = "ClientHandler";
/**
* 当收到数据的回调
*
* @param channelHandlerContext 封装的连接对像
* @param o
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
}
/**
* 与服务端连接成功的回调
*
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
Log.d(TAG, "与服务端连接成功:" + ctx.toString());
}
/**
* 与服务端断开的回调
*
* @param ctx
* @throws Exception
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
Log.d(TAG, "与服务端断开连接:" + ctx.toString());
}
}
四、先启动服务端 在启动客户端,这样就可以建立起连接了
- 启动服务端
NettyServer server = new NettyServer();
server.startServer();
- 启动客户端
NettyClient client = NettyClient.getInstance();
- 运行效果
五、下一篇文章将着重对Encoder
、Decoder
和Handler
进行讲解说明
Demo将会在本系列文章第四篇文章中给出
转载:https://blog.csdn.net/a_zhon/article/details/100569489
查看评论