### 前言
之前已经讲过了`Netty`实现的`UDP`通讯。大家感兴趣的可以参考以下文章:
[Netty实现UDP客户端](http://www.demodashi.com/demo/17159.html)
[Netty实现UDP服务端](http://www.demodashi.com/demo/17160.html)
那么今天给大家介绍一个新的通讯框架——`MINA`,之所以要介绍`mina`,是因为它在通讯`长连接`方面有比较大的优势。今天就让我们来了解下`mina`利用`tcp`实现`长连接客户端`吧。
今天涉及以下内容:
1. mina官网及实现客户端需要的jar包
2. mina客户端的几个类
3. TmClientManager在activity中的使用
4. 通讯前提及需要注意的问题
5. 效果图和项目结构图
先来波效果图
![效果图.gif](/contentImages/image/20200623/cR0vcxzpG4oyZaqeo9l.gif)
#### 一. mina官网及实现客户端需要的jar包
`mina`是一个通讯长连接框架,其官网如下:
[mina官网](http://mina.apache.org/)
利用`mina`实现`tcp长连接客户端`需要以下`jar`包:
```
mina-core-2.0.16.jar
slf4j-android-1.7.21.jar
slf4j-api-1.7.21.jar
```
下载地址:[mina_tcp客户端jar.zip](https://download.csdn.net/download/Burn_yourself/12542994)
大家将以上jar下载下来,然后导入到自己的项目中。
#### 二.mina客户端的几个类
实现`mina`长连接客户端我写了几个类,这几个类分工处理通讯的各个环节,下面对它们进行一个简单的介绍:
- SessionManager:客户端用于收发消息的`session`,此类单例,利用它可以向服务端发送消息
- TmClientHandler:客户端实际接收消息类,服务端返回消息及客户端发送的消息均要经过此类
- TmClientManager:客户端连接操作对象,封装tcp连接的`建立连接`、`断开连接`方法
- TmClientConfig:客户端连接配置类。主要用于设置连接参数,然后接收服务端返回数据
其中`SessionManager`采用单例模式实现,`TmClientConfig`采用建造者模式
#### 三.TmClientManager在activity中的使用
`mina`客户端的使用流程大致如下:
```
//声明tcp客户端操作对象和配置对象
private TmClientConfig mConfig;
private TmClientManager mTmClientManager;
/**初始化数据**/
private void initData(){
//初始化tcp配置
mConfig=new TmClientConfig.Builder(TempActivity.this)
.setIp("192.168.50.152")//设置服务端ip
.setPort(9124)//设置端口(0-65535)之间
// .setConnectTimeOut(30000)//设置连接超时时间,单位毫秒,默认30000,即30秒
// .setCharsetName("UTF-8")//设置字符集,默认为 “UTF-8”
// .setReadBufferSize(2048)//设置接收数据缓存区,默认2048
//设置mina客户端接收数据监听
.setCmrListener(new TmClientHandler.OnMessageReceivedListener() {
@Override
public void messageReceived(IoSession session, Object message) {
//接收服务端消息
//......
LogUtil.i("======我是服务端返回消息==message="+message.toString());
}
}).build();
//初始化操作对象
mTmClientManager=new TmClientManager(mConfig);
}
//给服务端发送消息
SessionManager.getInstance().writeToServer("abc");
//断开连接
mTmClientManager.disConnect();
```
下面来看看`activity`中的使用示例吧:
```
/**
* Title:测试界面
* description:
* autor:pei
* created on 2020/6/2
*/
public class TempActivity extends AppCompatActivity implements View.OnClickListener{
private TextView mTv;
private Button mBtn1;
private Button mBtn2;
//声明tcp客户端操作对象和配置对象
private TmClientConfig mConfig;
private TmClientManager mTmClientManager;
@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);
mBtn1=findViewById(R.id.btn1);
mBtn2=findViewById(R.id.btn2);
}
/**初始化数据**/
private void initData(){
//初始化tcp配置
mConfig=new TmClientConfig.Builder(TempActivity.this)
.setIp("192.168.50.152")//设置服务端ip
.setPort(9124)//设置端口(0-65535)之间
// .setConnectTimeOut(30000)//设置连接超时时间,单位毫秒,默认30000,即30秒
// .setCharsetName("UTF-8")//设置字符集,默认为 “UTF-8”
// .setReadBufferSize(2048)//设置接收数据缓存区,默认2048
//设置mina客户端接收数据监听
.setCmrListener(new TmClientHandler.OnMessageReceivedListener() {
@Override
public void messageReceived(IoSession session, Object message) {
//接收服务端消息
//......
LogUtil.i("======我是服务端返回消息==message="+message.toString());
}
}).build();
//初始化操作对象
mTmClientManager=new TmClientManager(mConfig);
}
/**设置监听**/
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===");
test();
break;
case R.id.btn2://测试2
//给服务端发送消息
SessionManager.getInstance().writeToServer("abc");
break;
default:
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//断开连接
mTmClientManager.disConnect();
}
/**测试**/
private void test(){
ToastUtil.shortShow("我是第一条测试");
new Thread(new Runnable() {
@Override
public void run() {
//连接服务端
mTmClientManager.connect();
}
}).start();
}
}
```
#### 四.通讯前提及需要注意的问题
需要注意的问题主要有:
- 项目的`manifast.xml`中要加网络权限,若涉及到其他权限的话,也要注意添加
- 服务端与客户端要使用相同的`字符集编码`,防止通讯过程中出现发送和接收数据乱码
- 客户端与服务端通讯不通的话,可以考虑从以下几个方面排查(包括单不限于):
```
1. mina_tcp客户端与服务端链接地址(ip)不一致
2. mina_tcp客户端与服务端链接端口(port)不一致
3. mina_tcp服务端未开启
4. mina_tcp客户端未联网或未开联网权限
5. mina_tcp客户端与服务端不在一个网段
```
#### 五. 效果图和项目结构图
![效果图.gif](/contentImages/image/20200623/cR0vcxzpG4oyZaqeo9l.gif)
项目结构图如下:
![image.png](/contentImages/image/20200623/r8FU9McIm7jHrM6y4iL.png)
ok,今天的内容就到这里了,谢谢大家。