MINA框架客户端的使用
在网络通信中,有时候需要保持长连接,一般的处理方式是使用socket,但是socket是阻塞式的,并且自己拼写socket的时候,步骤也挺繁杂,很容易出错。因此就想到了使用底层封装socket的框架---MINA框架。MINA框架的客户端是很好处理的,但是服务端网上大多是main函数来实现的。实际项目中,通常有很多需要tomcat来启动,因此就需要整合tomcat和MINA框架。本篇主要介绍MINA框架的获取以及客户端的使用。下一遍主要讲在服务端的使用,以及如何整合到tomcat中。
这个是MINA框架的下载地址 http://mina.apache.org/downloads-mina.html
打开后界面如下:
一个是当前版本的下载,一个是历史版本的下载。点击当前版本下载以后,会跳抓到下一个界面
点击红框处即可下载。当下载完成以后是个zip的压缩包,我们需要的jar包就放在这个压缩包里。网上有很多demo,用到了MINA的三四个jar包。但是,如果只需要满足基本的通信功能,两个jar包就行了。
把压缩包解压出来,会出现三个文件夹,其中dist文件夹里有个mina-core-2.0.16.jar,lib文件夹里有个slf4j-api-1.7.21.jar。这两个jar包就是我们需要的jar。如果是不同的版本,版本号会不一样。即mina-core-版本号.jar和slf4j-api-版本号.jar。我们把这两个jar放入我们的工程就可以开始编码了。
下面直接上代码:
==============================================================================
主界面MainActivity很简单,三个按钮,分别是开启服务,关闭服务,和点击发送消息的按钮。这里把与服务器的通信放到了service中进行处理。
package com.testdog.activity;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.dog.minaclient.R;
import com.testdog.manager.SessionManager;
import com.testdog.service.TestService;
public class MainActivity extends BaseActivity {
@Override
protected void init() {
// 在main里面把后台服务开启,然后主动连接服务器
setContentView(R.layout.activity_main);
Button btn_start = (Button) findViewById(R.id.btn_start);
Button btn_end = (Button) findViewById(R.id.btn_end);
Button btn_send = (Button) findViewById(R.id.btn_send);
btn_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, TestService.class);
startService(intent);
}
});
btn_end.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, TestService.class);
stopService(intent);
}
});
btn_send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SessionManager.getInstance().writeToServer("hello123");
}
});
}
}
===========================================================================
主界面的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是主界面"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动服务"
android:id="@+id/btn_start"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关闭服务"
android:id="@+id/btn_end"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送数据"
android:id="@+id/btn_send"/>
</LinearLayout>
===========================================================================
BaseActivity中主要是用于广播事件的注册,接收从服务器发过来的消息进行处理
package com.testdog.activity;
import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import com.testdog.broadcast.MessageBroadcastReceiver;
public abstract class BaseActivity extends Activity {
private MessageBroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerBroadcast();
init();
}
protected abstract void init();
private void registerBroadcast() {
receiver = new MessageBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.commonlibrary.mina.broadcast");
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,filter);
}
private void unregisterBroadcast(){
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterBroadcast();
}
}
===========================================================================
广播接收者类:
package com.testdog.broadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MessageBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// 接受到广播以后进行判断,更具操作进行相应的跳转
String a = (String) intent.getExtras().get("message");
Toast.makeText(context, a, 0).show();
}
}
====================================================================
服务器的访问ip配置类
package com.testdog.config;
import android.content.Context;
/**
* Description:构建者模式
*/
public class ConnectionConfig {
private Context context;
private String ip;
private int port;
private int readBufferSize;
private long connectionTimeout;
public Context getContext() {
return context;
}
public String getIp() {
return ip;
}
public int getPort() {
return port;
}
public int getReadBufferSize() {
return readBufferSize;
}
public long getConnectionTimeout() {
return connectionTimeout;
}
public static class Builder{
private Context context;
private String ip = "192.168.168.20";
private int port = 9226;
private int readBufferSize = 10240;
private long connectionTimeout = 10000;
public Builder(Context context){
this.context = context;
}
public Builder setIp(String ip){
this.ip = ip;
return this;
}
public Builder setPort(int port){
this.port = port;
return this;
}
public Builder setReadBufferSize(int readBufferSize){
this.readBufferSize = readBufferSize;
return this;
}
public Builder setConnectionTimeout(long connectionTimeout){
this.connectionTimeout = connectionTimeout;
return this;
}
private void applyConfig(ConnectionConfig config){
config.context = this.context;
config.ip = this.ip;
config.port = this.port;
config.readBufferSize = this.readBufferSize;
config.connectionTimeout = this.connectionTimeout;
}
public ConnectionConfig builder(){
ConnectionConfig config = new ConnectionConfig();
applyConfig(config);
return config;
}
}
}
==========================================================================
链接服务器的管理类,主要是对MINA框架的一些配置,以及编解码规则。
package com.testdog.manager;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.prefixedstring.PrefixedStringCodecFactory;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import com.testdog.config.ConnectionConfig;
import java.lang.ref.WeakReference;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
/**
* Description:
*/
public class ConnectionManager {
private static final String BROADCAST_ACTION = "com.commonlibrary.mina.broadcast";
private static final String MESSAGE = "message";
private ConnectionConfig mConfig;
private WeakReference<Context> mContext;
private NioSocketConnector mConnection;
private IoSession mSession;
private InetSocketAddress mAddress;
public ConnectionManager(ConnectionConfig config) {
this.mConfig = config;
this.mContext = new WeakReference<Context>(config.getContext());
init();
}
private void init() {
mAddress = new InetSocketAddress(mConfig.getIp(), mConfig.getPort());
try {
mConnection = new NioSocketConnector();
mConnection.getSessionConfig().setReadBufferSize(mConfig.getReadBufferSize());
mConnection.getFilterChain().addLast("logging", new LoggingFilter());
mConnection.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(),
LineDelimiter.WINDOWS.getValue())));
mConnection.setHandler(new DefaultHandler(mContext.get()));
mConnection.setDefaultRemoteAddress(mAddress);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 与服务器连接
*
* @return
*/
public boolean connnect() {
Log.e("tag", "准备连接");
try {
ConnectFuture future = mConnection.connect();
future.awaitUninterruptibly();
mSession = future.getSession();
SessionManager.getInstance().setSeesion(mSession);
} catch (Exception e) {
e.printStackTrace();
Log.e("tag", "连接失败");
return false;
}
return mSession == null ? false : true;
}
/**
* 断开连接
*/
public void disContect() {
mConnection.dispose();
mConnection = null;
mSession = null;
mAddress = null;
mContext = null;
Log.e("tag", "断开连接");
}
private static class DefaultHandler extends IoHandlerAdapter {
private Context mContext;
private DefaultHandler(Context context) {
this.mContext = context;
}
@Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
Log.e("tag", "接收到服务器端消息:" + message.toString());
if (mContext != null) {
Intent intent = null;
// 在这里进行判断服务器发过来的消息类别
if("出库".equals("出库")){
intent = new Intent(BROADCAST_ACTION);
} else if("入库".equals("")){
intent = new Intent(BROADCAST_ACTION);
} else {
//......
}
intent.putExtra(MESSAGE, message.toString());
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
}
}
}
}
messageReceived方法用来接收服务器发来的消息,然后把消息通过广播发送出去并做相应的处理。我这里是出库入库事件,而实际应用过程中,具体逻辑需要根据具体的需求去写。
==============================================================================
session管理器。session对象是客户端和服务器端进行通信的基础。通过session对象可以写入或者写出数据。每一个客户端链接服务器都会生成一个session对象。如果多个客户端同时连接服务器,可以使用Map集合把session对象存起来。
package com.testdog.manager;
import android.util.Log;
import org.apache.mina.core.session.IoSession;
/**
* Description: User: chenzheng Date: 2016/12/9 0009 Time: 17:50
*/
public class SessionManager {
private static SessionManager mInstance = null;
private IoSession mSession;
public static SessionManager getInstance() {
if (mInstance == null) {
synchronized (SessionManager.class) {
if (mInstance == null) {
mInstance = new SessionManager();
}
}
}
return mInstance;
}
private SessionManager() {
}
public void setSeesion(IoSession session) {
this.mSession = session;
}
public void writeToServer(String msg) {
if (mSession != null) {
Log.e("tag", "客户端准备发送消息");
mSession.write(msg);
}
}
public void closeSession() {
if (mSession != null) {
mSession.closeOnFlush();
}
}
public void removeSession() {
this.mSession = null;
}
}
===================================================================================
后台服务类代码
package com.testdog.service;
import com.testdog.thread.MyThread;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
/**
* 后台运行的服务,用来处理一些后台逻辑,比如接收到来自服务器端的请求以后,进行一些界面上的处理
*
* @author Administrator
*
*/
public class TestService extends Service {
private MyThread myThread;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// 在onCreate方法里连接服务器
myThread = new MyThread("mina", getApplicationContext());
// 启动线程
myThread.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
myThread.disConnect();
// 把进程杀死
myThread.interrupt();
}
}
===================================================================
后台运行的线程自定义线程
package com.testdog.thread;
import com.testdog.config.ConnectionConfig;
import com.testdog.manager.ConnectionManager;
import android.content.Context;
import android.os.HandlerThread;
import android.util.Log;
public class MyThread extends HandlerThread {
private Context mContext;
boolean isConnection;
ConnectionManager mManager;
public MyThread(String name, Context context) {
super(name);
mContext = context;
// 主动连接服务器
// 连接服务器的配置类
ConnectionConfig config = new ConnectionConfig.Builder(context)
.setIp("192.168.1.190").setPort(10086).setReadBufferSize(2048)
.setConnectionTimeout(10000).builder();
// 连接服务器的管理类
mManager = new ConnectionManager(config);
}
/**
* loop循环,用来处理与服务器的连接
*/
@Override
protected void onLooperPrepared() {
// 死循环,如果连不上服务器,会一直在后台自动检测连接服务器
while (true) {
isConnection = mManager.connnect();
if (isConnection) {
// 说明连接服务器成功
Log.e("tag", "连接成功");
break;
}
try {
Log.e("tag", "尝试重新连接");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void disConnect(){
mManager.disContect();
}
}
=======================================================================================
清单文件中添加的权限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
清单文件中添加服务
<service android:name="com.testdog.service.TestService" ></service>
好了,这就是demo全部代码,只要全部粘贴过去就能使用了,以上亲测可用。服务端整合tomcat由于篇幅太长了,将在下篇中贴出来。
MINA框架客户端的使用相关推荐
- Camera开发系列之六-使用mina框架实现视频推流
章节 Camera开发系列之一-显示摄像头实时画面 Camera开发系列之二-相机预览数据回调 Camera开发系列之三-相机数据硬编码为h264 Camera开发系列之四-使用MediaMuxer封 ...
- 基于MINA框架快速开发网络应用程序
1.MINA框架简介 MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架.通过使用 ...
- Mina框架项目运用
近期最一个项目对通信要求比較严格,须要建立长连接,且能处理多并发,所以选择了Mina框架.以下就简单记录开发的过程吧: mina 开发须要的jar包: mina pc端通信: 服务端: package ...
- 搭建Apache Mina框架并实现Server与Client端的简单消息传递
http://www.himigame.com/apache-mina/831.html :(作者新浪微博: @李华明Himi ) 转载自[黑米GameDev街区] 原文链接: http://www. ...
- Mina框架并实现Server与Client端的简单消息传递!
Hibernate系列学习阶段到此结束了,那么紧接着进入Apache Mina的开发学习,很多童鞋在微薄和QQ中疑问Himi为什么突然脱离游戏开发了,嘿嘿,其实可能更多的童鞋已经看出来了,Himi在偏 ...
- 【Apache Mina2.0开发之一】搭建Apache Mina框架并实现Server与Client端消息传递
Hibernate系列学习阶段到此结束了,那么紧接着进入Apache Mina的开发学习,很多童鞋在微薄和QQ中疑问Himi为什么突然脱离游戏开发了,嘿嘿,其实可能更多的童鞋已经看出来了,Himi在偏 ...
- 游戏服务器Mina框架开发
游戏服务器Mina框架开发 作者:老九-技术大黍 社交:知乎 公众号:老九学堂(新人有惊喜) 特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系笔者授权 前言 如果要使用Java语言来开发游戏 ...
- java mina框架实例_Apache Mina框架实践
1.为什么要用Apache Mina框架 ApacheMina Server 是一个网络通信应用框架,Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mi ...
- Apache MINA框架快速入门
一.为什么要用MINA框架 Apache Mina是一个网络通信应用框架,是基于TCP/IP.UDP/IP协议栈的通信框架,Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持,具有高性能 ...
- 朝花夕拾之socket的基本使用以及mina框架简单介绍
工欲善其事,必先利其器,从互联网诞生到现在,基本上所有的程序都是网络程序,很少有单机版的程序了. 而网络编程的本质是两个设备之间的数据交换,当然,在计算机网络中,设备主要指计算机.我们现在进行网络编程 ...
最新文章
- 判断出栈顺序是否正确(栈的压入、弹出序列)
- 皮一皮:碰上一个说倒装句的直男怎么办...
- BZOJ 3529: [Sdoi2014]数表
- mysql三大范式 答案_数据库三大范式的个人理解~!
- 理解SQLNET.AUTHENTICATION_SERVICES参数
- 算法 --- 反转数组
- 利用samba服务为windows用户架设网盘的简单实践
- easyui下datagrid列单独赋值
- DOM_xss预备知识
- 高中信息技术python及答案_(完整)高中信息技术《Python语言》模块试卷
- 如何使用Python制作网站?
- 什么是大型机和小型机
- 申论阅读:心中有爱,方能遇见更好的自己
- ubuntu18.04安装Nvidia显卡驱动后黑屏及网络、蓝牙驱动消失的解决方案
- php篮球比赛,篮球数据API接口-【篮球比赛动画直播变化数据】API调用示例代码...
- Marioの《计算机程序设计艺术》读书笔记:数学归纳法
- linux软件保护,国产Linux违反《计算机软件保护条例》的说明
- [Beta] Scrum Meeting 9 - TEAM LESS ERROR
- 坐标变换学习笔记—代码篇Matlab
- android 相机拍照返回,Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题...
热门文章
- 『vulnhub系列』dpwwn-1—Linux计划任务提权
- Crontab 在线生成器 - Linux计划任务
- python数据透视表对各列统计_python pandas数据分析基础入门2——(数据格式转换、排序、统计、数据透视表)...
- 连连看游戏辅助工具python版的实现
- linux如何设置显示器亮度调节软件,为 Linux 启用色温和亮度调节工具
- 风云再续:他抖任他抖,IO诊断在我手
- flash播放器代码
- 各位大佬,Spark的重点难点系列暂时更新完毕
- ModuleNotFoundError: No module named ‘keras.api‘解决
- 二级计算机vf题型,计算机二级VF题型有哪些?