Mina长连接框架实现Android客户端与服务器端通信

来源:互联网 发布:linux脚本文件格式 编辑:程序博客网 时间:2024/04/28 00:47

一、概述

        Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。


二、服务器端代码

MinaService.java

package com.czhappy.mina;import java.net.InetSocketAddress;import java.util.Date;import org.apache.mina.core.service.IoAcceptor;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;import org.apache.mina.filter.logging.LoggingFilter;import org.apache.mina.transport.socket.nio.NioSocketAcceptor;public class MinaService {public static void main(String[] args) {IoAcceptor acceptor = new NioSocketAcceptor();//添加日志过滤器acceptor.getFilterChain().addLast("logger", new LoggingFilter());acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));acceptor.setHandler(new DemoServerHandler());acceptor.getSessionConfig().setReadBufferSize(2048);acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);try {acceptor.bind(new InetSocketAddress(9226));} catch (Exception e) {e.printStackTrace();}System.out.println("启动服务");}/**   * @ClassName: DemoServerHandler   * @Description: 负责session对象的创建和监听以及消息的创建和接收监听 * @author chenzheng * @date 2016-12-9 下午3:57:11   */private static class DemoServerHandler extends IoHandlerAdapter{//服务器与客户端创建连接@Overridepublic void sessionCreated(IoSession session) throws Exception {System.out.println("服务器与客户端创建连接...");super.sessionCreated(session);}@Overridepublic void sessionOpened(IoSession session) throws Exception {System.out.println("服务器与客户端连接打开...");super.sessionOpened(session);}//消息的接收处理@Overridepublic void messageReceived(IoSession session, Object message)throws Exception {// TODO Auto-generated method stubsuper.messageReceived(session, message);String str = message.toString();Date date = new Date();session.write(date.toString());System.out.println("接收到的数据:"+str);}@Overridepublic void messageSent(IoSession session, Object message)throws Exception {// TODO Auto-generated method stubsuper.messageSent(session, message);}@Overridepublic void sessionClosed(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionClosed(session);}}}

三、Android客户端代码

ConnectionConfig.java

package com.czhappy.minaclient;import android.content.Context;/** * Description:构建者模式 * User: chenzheng * Date: 2016/12/9 0009 * Time: 16:37 */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;        }    }}

ConnectionManager.java

package com.czhappy.minaclient;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.serialization.ObjectSerializationCodecFactory;import org.apache.mina.filter.logging.LoggingFilter;import org.apache.mina.transport.socket.nio.NioSocketConnector;import java.lang.ref.WeakReference;import java.net.InetSocketAddress;/** * Description: * User: chenzheng * Date: 2016/12/9 0009 * Time: 16:21 */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());        mConnection = new NioSocketConnector();        mConnection.getSessionConfig().setReadBufferSize(mConfig.getReadBufferSize());        mConnection.getFilterChain().addLast("logging", new LoggingFilter());        mConnection.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));        mConnection.setHandler(new DefaultHandler(mContext.get()));        mConnection.setDefaultRemoteAddress(mAddress);    }    /**     * 与服务器连接     * @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 = new Intent(BROADCAST_ACTION);                intent.putExtra(MESSAGE, message.toString());                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);            }        }    }}

MinaService.java

package com.czhappy.minaclient;import android.app.Service;import android.content.Context;import android.content.Intent;import android.os.HandlerThread;import android.os.IBinder;import android.support.annotation.Nullable;import android.util.Log;/** * Description: * User: chenzheng * Date: 2016/12/9 0009 * Time: 17:17 */public class MinaService extends Service{    private ConnectionThread thread;    @Override    public void onCreate() {        super.onCreate();        thread = new ConnectionThread("mina", getApplicationContext());        thread.start();        Log.e("tag", "启动线程尝试连接");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        thread.disConnect();        thread=null;    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    class ConnectionThread extends HandlerThread{        private Context context;        boolean isConnection;        ConnectionManager mManager;        public ConnectionThread(String name, Context context){            super(name);            this.context = context;            ConnectionConfig config = new ConnectionConfig.Builder(context)                    .setIp("192.168.168.20")                    .setPort(9226)                    .setReadBufferSize(10240)                    .setConnectionTimeout(10000).builder();            mManager = new ConnectionManager(config);        }        @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();        }    }}

SessionManager.java

package com.czhappy.minaclient;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(Object msg){        if(mSession!=null){            Log.e("tag", "客户端准备发送消息");            mSession.write(msg);        }    }    public void closeSession(){        if(mSession!=null){            mSession.closeOnFlush();        }    }    public void removeSession(){        this.mSession=null;    }}

MinaTestActivity.java

package com.czhappy.minaclient;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.support.v4.content.LocalBroadcastManager;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.TextView;/** * Description: * User: chenzheng * Date: 2016/12/9 0009 * Time: 18:01 */public class MinaTestActivity extends AppCompatActivity implements View.OnClickListener{    private TextView start_service_tv, send_tv, receive_tv;    private MessageBroadcastReceiver receiver;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_mina_test);        initView();        registerBroadcast();    }    private void registerBroadcast() {        receiver = new MessageBroadcastReceiver();        IntentFilter filter = new IntentFilter("com.commonlibrary.mina.broadcast");        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);    }    private void initView() {        receive_tv = (TextView) this.findViewById(R.id.receive_tv);        start_service_tv = (TextView) this.findViewById(R.id.start_service_tv);        start_service_tv.setOnClickListener(this);        send_tv = (TextView) this.findViewById(R.id.send_tv);        send_tv.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch(v.getId()){            case R.id.start_service_tv:                Log.e("tag", "点击启动服务");                Intent intent = new Intent(this, MinaService.class);                startService(intent);                break;            case R.id.send_tv:                Log.e("tag", "点击发送消息");                SessionManager.getInstance().writeToServer("hello123");                break;        }    }    private void unregisterBroadcast(){        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);    }    @Override    protected void onDestroy() {        super.onDestroy();        stopService(new Intent(this, MinaService.class));        unregisterBroadcast();    }    private class MessageBroadcastReceiver extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            receive_tv.setText(intent.getStringExtra("message"));        }    }}

四、运行结果

1.点击启动服务,观察客户端是否与服务器端连接成功;

2.点击发送消息,观察消息是否发送成功,如果失败判断失败在哪一步。

客户端运行结果:


服务器端运行结果:


五、源码下载

http://download.csdn.net/detail/chenzheng8975/9707406


2 0