文章出处:https://blog.csdn.net/chenzheng8975/article/details/53558387
本篇文章和出处一样 只是加了一些注释
1.mina服务器搭建
搭建思路 --调用mina为我们提供的服务器API即可完成
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{
//服务器与客户端创建连接
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("服务器与客户端创建连接...");
super.sessionCreated(session);
}
@Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("服务器与客户端连接打开...");
super.sessionOpened(session);
}
//消息的接收处理
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
super.messageReceived(session, message);
String str = message.toString();
Date date = new Date();
session.write(date.toString());
System.out.println("接收到的数据:"+str);
}
@Override
public void messageSent(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
super.messageSent(session, message);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
// TODO Auto-generated method stub
super.sessionClosed(session);
}
}
}
2.mina客户端工程创建
需要jar包 mina-core-2.0.16.jar 和 slf4j-android-1.6.1-RC1.jar
创建一个Service,用来与远程服务器连接
封装一个ConnectionManager类用来提供与服务器连接的方法,ConnectionManager写成一个单利的 双加锁
在Service中启动线程,调用ConnectionManager完成连接的创建,Service中的IOSession 消息接受的到后用局部广播发送出去
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;
}
//--------在构建者模式中 以上代码是 先写的 默认-------------------
// 通过Builder内部类
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;//10秒
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 {
//广播的acton 一般使用包名 命名
private static final String BROADCAST_ACTION = "com.commonlibrary.mina.broadcast";
private static final String MESSAGE = "message";
private ConnectionConfig mConfig;//要配置一些参数 ip 端口,在这里使用构建者模式,动态的设置
private WeakReference<Context> mContext;//为了确保防止内存溢出,使用弱引用 对context一层包装
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 disContection(){
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 {
//将我们的session保存到我们的session manager类中,从而可以发送消息到服务器
}
@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);//开始想使用第三方的框架relsbus将消息抛出去,后来感觉太依赖这个框架,这样不太好,最后就Android自带的广播机制将消息发送出去,使用局部广播 将收到的消息 发出去,其他app监听不到 比较安全
}
}
}
}
MinaService.java 使用Service 调用ConnectionManager来完成与服务器之间的连接
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;
}
/**
* 负责调用connection manager类来完成与服务器的连接
* 这也可以用普通的Thread 这里演示了HandlerThread的使用
*/
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);
}
/**
* 开始连接我们的服务器
* 这个方法相当于普通线程中的run()方法
*/
@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 disConnection(){
mManager.disContection();//完成与服务器的断开操作
}
}
}
SessionManager.java
package com.czhappy.minaclient;
import android.util.Log;
import org.apache.mina.core.session.IoSession;
/**
* Description: Session管理的单利对象,双加锁机制
* 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"));
}
}
}
3.运行结果
1.点击启动服务,观察客户端是否与服务器端连接成功;
2.点击发送消息,观察消息是否发送成功,如果失败判断失败在哪一步。
客户端运行结果:
服务器端运行结果:
4.源码下载
http://download.csdn.net/detail/chenzheng8975/9707406
50积分下载