在网络通信中,有时候需要保持长连接,一般的处理方式是使用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框架客户端的使用相关推荐

  1. Camera开发系列之六-使用mina框架实现视频推流

    章节 Camera开发系列之一-显示摄像头实时画面 Camera开发系列之二-相机预览数据回调 Camera开发系列之三-相机数据硬编码为h264 Camera开发系列之四-使用MediaMuxer封 ...

  2. 基于MINA框架快速开发网络应用程序

    1.MINA框架简介  MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架.通过使用 ...

  3. Mina框架项目运用

    近期最一个项目对通信要求比較严格,须要建立长连接,且能处理多并发,所以选择了Mina框架.以下就简单记录开发的过程吧: mina 开发须要的jar包: mina pc端通信: 服务端: package ...

  4. 搭建Apache Mina框架并实现Server与Client端的简单消息传递

    http://www.himigame.com/apache-mina/831.html :(作者新浪微博: @李华明Himi ) 转载自[黑米GameDev街区] 原文链接: http://www. ...

  5. Mina框架并实现Server与Client端的简单消息传递!

    Hibernate系列学习阶段到此结束了,那么紧接着进入Apache Mina的开发学习,很多童鞋在微薄和QQ中疑问Himi为什么突然脱离游戏开发了,嘿嘿,其实可能更多的童鞋已经看出来了,Himi在偏 ...

  6. 【Apache Mina2.0开发之一】搭建Apache Mina框架并实现Server与Client端消息传递

    Hibernate系列学习阶段到此结束了,那么紧接着进入Apache Mina的开发学习,很多童鞋在微薄和QQ中疑问Himi为什么突然脱离游戏开发了,嘿嘿,其实可能更多的童鞋已经看出来了,Himi在偏 ...

  7. 游戏服务器Mina框架开发

    游戏服务器Mina框架开发 作者:老九-技术大黍 社交:知乎 公众号:老九学堂(新人有惊喜) 特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系笔者授权 前言 如果要使用Java语言来开发游戏 ...

  8. java mina框架实例_Apache Mina框架实践

    1.为什么要用Apache Mina框架 ApacheMina Server 是一个网络通信应用框架,Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mi ...

  9. Apache MINA框架快速入门

    一.为什么要用MINA框架 Apache Mina是一个网络通信应用框架,是基于TCP/IP.UDP/IP协议栈的通信框架,Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持,具有高性能 ...

  10. 朝花夕拾之socket的基本使用以及mina框架简单介绍

    工欲善其事,必先利其器,从互联网诞生到现在,基本上所有的程序都是网络程序,很少有单机版的程序了. 而网络编程的本质是两个设备之间的数据交换,当然,在计算机网络中,设备主要指计算机.我们现在进行网络编程 ...

最新文章

  1. 判断出栈顺序是否正确(栈的压入、弹出序列)
  2. 皮一皮:碰上一个说倒装句的直男怎么办...
  3. BZOJ 3529: [Sdoi2014]数表
  4. mysql三大范式 答案_数据库三大范式的个人理解~!
  5. 理解SQLNET.AUTHENTICATION_SERVICES参数
  6. 算法 --- 反转数组
  7. 利用samba服务为windows用户架设网盘的简单实践
  8. easyui下datagrid列单独赋值
  9. DOM_xss预备知识
  10. 高中信息技术python及答案_(完整)高中信息技术《Python语言》模块试卷
  11. 如何使用Python制作网站?
  12. 什么是大型机和小型机
  13. 申论阅读:心中有爱,方能遇见更好的自己
  14. ubuntu18.04安装Nvidia显卡驱动后黑屏及网络、蓝牙驱动消失的解决方案
  15. php篮球比赛,篮球数据API接口-【篮球比赛动画直播变化数据】API调用示例代码...
  16. Marioの《计算机程序设计艺术》读书笔记:数学归纳法
  17. linux软件保护,国产Linux违反《计算机软件保护条例》的说明
  18. [Beta] Scrum Meeting 9 - TEAM LESS ERROR
  19. 坐标变换学习笔记—代码篇Matlab
  20. android 相机拍照返回,Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题...

热门文章

  1. 『vulnhub系列』dpwwn-1—Linux计划任务提权
  2. Crontab 在线生成器 - Linux计划任务
  3. python数据透视表对各列统计_python pandas数据分析基础入门2——(数据格式转换、排序、统计、数据透视表)...
  4. 连连看游戏辅助工具python版的实现
  5. linux如何设置显示器亮度调节软件,为 Linux 启用色温和亮度调节工具
  6. 风云再续:他抖任他抖,IO诊断在我手
  7. flash播放器代码
  8. 各位大佬,Spark的重点难点系列暂时更新完毕
  9. ModuleNotFoundError: No module named ‘keras.api‘解决
  10. 二级计算机vf题型,计算机二级VF题型有哪些?