概述
利用netty实现Android上tcp客户端通讯
详细
前言
今天就来讲讲用Netty实现TCP客户端。我将Netty实现的TCP客户端封装到了两个类中,分别是:TnClientHandler和TnServer,下面就介绍TnServer的使用吧。今天涉及内容:
- 为什么要用Netty
- nettyjar 包导入
- TnClientHandler和TnClient简介
- TnClient在Activity中的使用
- 需要注意的地方
- 效果图和项目结构图
先来波效果图
一. 为什么要用Netty
之前已经讲过了Tcp客户端封装的一篇文章了,基本可以实现通讯需求。既然如此,那为啥还要讲Tcp基于Netty的实现呢?大家知道Tcp通讯是基于三次握手,建立通道,然后通过IO流进行数据交互的,而基于JDK版本的发展,NIO在数据流传输上比原始的IO流有了很大的提升,那为啥不直接使用NIO代替IO用TCP传输,原因是NIO结构复杂,个人实现起来要做很多工作,而且仅仅用NIO的实现在通讯方面存在一定的bug,Netty正式基于NIO实现的网络通讯框架,其修复NIO在通讯传输上的弊端,然后使用固定的api等,使得NIO实现的通讯稳定,学习起来也相对轻松。当然,netty绝不仅仅是这些,以上只是我针对netty在实现tcp通讯方面的部分优势介绍。接下来,让我们进入正题。
二. netty jar 包导入
在利用netty实现tcp通讯前,我们需要导入nettyjar包,我用的版本是netty-all-5.0.0.Alpha2.jar。首先我们要在你项目的 项目/app/下建lib文件夹,建成后路径为:项目/app/lib/,然后将netty-all-5.0.0.Alpha2.jar 复制 到 项目/app/lib/ 文件夹下。选中netty-all-5.0.0.Alpha2.jar 右键,选择 add As Library...,然后打开你app_module对应的build.gradle,看到以下代码:
implementation files('libs/netty-all-5.0.0.Alpha2.jar')
则表示你jar包导入成功。此处只做讲解,因为demo中已经帮你把nettyjar 包弄好了。
三. TnClientHandler 和 TnClient 简介
在使用的过程中我们主要用到的类是TnClient,TnClientHandler虽然是实现Tcp通讯客户端一个不可或缺的类,但是已经是作为一个netty tcp 客户端辅助类只为TnClient服务,使用者不必太多关注。因此,下面就来讲讲TnClient中的一些重要方法吧:
/**
* 初始化对象
*
* @param ip 服务端ip
* @param port 端口号 0-65535
*/
public TnClient(String ip,int port)
/**
* 发起通讯
*
* @param message 要发送的消息,字符串
* @param charsetName 字符集,如 TcpConfig.UTF_8 或 TcpConfig.GBK,为null时采用编译器默认字符集
* @param listener 接收服务端返回数据的监听
*/
public void channel(String message,String charsetName,TnClientHandler.OnChannelListener listener)
TnClient中的方法比较简单,这里主要注意的是channel(String message,String charsetName,TnClientHandler.OnChannelListener listener)方法中,message是客户端给服务端发送的消息,而listener中监听得到Tcp服务端给Tcp客户端返回的数据。
四. TnClient 在 Activity 中的使用
下面贴出TnClient在Activity中使用代码:
/**
* Title:测试界面
* description:
* autor:pei
* created on 2020/6/2
*/
public class TempActivity extends AppCompatActivity implements View.OnClickListener{
private TextView mTv;
private TextView mTv2;
private Button mBtn1;
private Button mBtn2;
private TnClient mTnClient;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_temp);
//初始化控件
initView();
//初始化数据
initData();
//设置监听
setListener();
}
/**初始化控件**/
private void initView(){
mTv=findViewById(R.id.tv);
mTv2=findViewById(R.id.tv2);
mBtn1=findViewById(R.id.btn1);
mBtn2=findViewById(R.id.btn2);
}
/**初始化数据**/
private void initData(){
mTnClient=new TnClient("192.168.50.152",1111);
}
/**设置监听**/
private void setListener(){
mBtn1.setOnClickListener(this);
mBtn2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1://测试1
LogUtil.i("=======测试1=======");
test1();
break;
case R.id.btn2://测试2
LogUtil.i("=======测试2=======");
test2();
break;
default:
break;
}
}
/**测试**/
private void test1(){
ToastUtil.shortShow("我是第一条测试");
mTnClient.channel("1我是第一条测试", "GBK", new TnClientHandler.OnChannelListener() {
@Override
public void success(ChannelHandlerContext ctx, String result) {
LogUtil.i("=====通讯成功==result=="+result);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTv.setText(result);
}
});
}
@Override
public void failed(ChannelHandlerContext ctx, Throwable cause) {
LogUtil.i("=======通讯失败======="+cause.getMessage());
}
});
}
/**测试**/
private void test2(){
ToastUtil.shortShow("我是第二条测试");
mTnClient.channel("2我是第二条测试", "GBK", new TnClientHandler.OnChannelListener() {
@Override
public void success(ChannelHandlerContext ctx, String result) {
LogUtil.i("=====通讯成功==result=="+result);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTv2.setText(result);
}
});
}
@Override
public void failed(ChannelHandlerContext ctx, Throwable cause) {
LogUtil.i("=======通讯失败======="+cause.getMessage());
}
});
}
}
五. 需要注意的地方
- 由于涉及通讯,在项目的manifast.xml中别忘了添加网络权限,若还需要其他权限,如文件读写权限,Android 6.0+ 权限等,也别网络加
- TnClient接收数据若有显示在界面的需求,一定要通过handler-message或runOnUiThread机制转换后再显示,不能直接将数据显示到控件上。
- TnClient在初始化的时候要注意ip和port的设置,既要符合值规范,也要让ip设置准确,port要保持服务端与客户端一致
- 要保持服务端与客户端在同一网段
- 测试的时候,手机要开启网络,若收不到服务端数据,可以看看是不是服务端为开启或已经异常停止
- 数据收发乱码问题,一定要保持服务端与客户端字符集编码一致
六. 效果图和项目结构图
ok,今天的内容就介绍到这里了,谢谢大家。