`
wmiao89620
  • 浏览: 26658 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

android之mina框架通信学习

阅读更多

这几天刚学期android,目前项目要求的客户端是android平台,所以要开始啃了....

服务器与客户端的通信准备使用现有的开发框架,找了几个----mina,google 的 protobuf,smack,androidpn,Netty...

这些框架都不错,不过最终选择的是apache的mina框架,主要是mina在网上的资料比较全,用的也比较广泛,再就是也适合我项目以后的扩展加入SPRING\CXF\RESTFUL WEBSERVICE等

不废话了,开始把目前学习的进度开始进行整理,方便自己以后进行查阅,也给其他入门的兄弟们 参考参考。

当然,最重要的是希望大家能够提出并给与宝贵的经验。

 

服务端代码:

package org.demo;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Demo1Server {
	private static Logger logger = LoggerFactory.getLogger(Demo1Server.class);

	private static int PORT = 8989;

	public static void main(String[] args) {
		IoAcceptor acceptor = null;
		try {
			
			// 创建一个非阻塞的server端的Socket
			acceptor = new NioSocketAcceptor();
			// 设置过滤器(使用Mina提供的文本换行符编解码器)
			acceptor.getFilterChain().addLast(
					"codec",
					new ProtocolCodecFilter(new TextLineCodecFactory(Charset
							.forName("UTF-8"),
							LineDelimiter.WINDOWS.getValue(),
							LineDelimiter.WINDOWS.getValue())));
			
			// 设置读取数据的缓冲区大小
			acceptor.getSessionConfig().setReadBufferSize(2048);
			// 读写通道10秒内无操作进入空闲状态
			acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
			// 绑定逻辑处理器
			acceptor.setHandler(new Demo1ServerHandler());
			// 绑定端口
			acceptor.bind(new InetSocketAddress(PORT));
			logger.info("服务端启动成功...     端口号为:" + PORT);
		} catch (Exception e) {
			logger.error("服务端启动异常....", e);
			e.printStackTrace();
		}
	}
}

 逻辑处理:

package org.demo;
import java.util.Date;

import net.sf.json.JSONObject;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoProcessor;
import org.apache.mina.common.IoSession;
import org.apache.mina.transport.socket.nio.NioProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo1ServerHandler extends IoHandlerAdapter{
	public static Logger logger = LoggerFactory.getLogger(Demo1ServerHandler.class);

	/** 
	* 这个方法当一个Session 对象被创建的时候被调用。对于TCP 连接来说,连接被接受的时候 
	* 调用,但要注意此时TCP 连接并未建立,此方法仅代表字面含义,也就是连接的对象 
	* IoSession 被创建完毕的时候,回调这个方法。 
	* 对于UDP 来说,当有数据包收到的时候回调这个方法,因为UDP 是无连接的。 
	*/ 
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		logger.info("服务端与客户端创建连接...");
	}

	/** 
	* 这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP 来 
	* 说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。 
	*/ 
	@Override
	public void sessionOpened(IoSession session) throws Exception {
		logger.info("服务端与客户端连接打开...");
	}

	/** 
	* 接收到消息时调用的方法,也就是用于接收消息的方法,一般情况下,message 是一个 
	* IoBuffer 类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。 
	*/ 
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		/*
		 String msg = message.toString();
		//读取数据
		logger.info("服务端接收到的数据为:" + msg+"客户端ip:"+session.getLocalAddress());
		if ("bye".equals(msg)) { // 服务端断开连接的条件
			session.close();
		}
		Date date = new Date();
		session.write(date);*/
		JSONObject jsonObject = JSONObject.fromObject(message.toString());
		String username; 
		String sex; 
		String qq; 
		String score; 
		String nickname;
		username = jsonObject.getString("username"); 
		sex = jsonObject.getString("sex"); 
		qq = jsonObject.getString("QQ"); 
		score = jsonObject.getString("Min.score");
		nickname = jsonObject.getString("nickname");
		int state = login(username);
		String msg = "登录成功!";
		if(state == 0){
			msg = "登录失败!";
		}
		logger.info("用户:" + username + msg);
		
		//模拟登陆
		if ("bye".equals(nickname)) { // 服务端断开连接的条件
			session.close();
		}
		//Date date = new Date();
		session.write(state);
	}

	//验证用户名 与 密码
		public int login(String message){
			if("sysadmin".equals(message)){
				return 1;
			}
			return 0;
		}
		
	/** 
	* 当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后, 
	* 也就是说发送消息是不能用这个方法的。 
	*/ 
	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		logger.info("服务端发送信息成功...");
	}

	/** 
	* 对于TCP 来说,连接被关闭时,调用这个方法。 
	* 对于UDP 来说,IoSession 的close()方法被调用时才会毁掉这个方法。 
	*/ 
	@Override
	public void sessionClosed(IoSession session) throws Exception {
		logger.info("服务端连接已经失效");
	}

	/** 
	* 这个方法在IoSession 的通道进入空闲状态时调用,对于UDP 协议来说,这个方法始终不会 
	* 被调用。 
	*/ 
	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		logger.info("服务端进入空闲状态...");
	}

	/** 
	* 这个方法在你的程序、Mina 自身出现异常时回调,一般这里是关闭IoSession。 
	*/ 
	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		logger.error("服务端发送异常...", cause);
	}

}

 客户端代码:

package org.demo;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.IoConnector;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

/**
 * @author wangmiao
 * @version 创建时间:2012-4-24 下午10:57:53 简单说明
 */
public class HelloWorld2 extends Activity {
	private static Logger logger = LoggerFactory.getLogger(HelloWorld2.class);
	private static String HOST = "192.168.1.100";

	private static int PORT = 8989;
	private static String LOGIN_NAME = "";

	public HelloWorld2() {

	}
	Handler handler = new Handler();


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		System.out.println(1);
		/*
		 * new Thread() { public void run() { socketServer(); } }.start();
		 */
		Button btn = (Button) findViewById(R.id.button1);
		btn.setOnClickListener(new OnClickListener() {
			EditText name = (EditText) findViewById(R.id.username);
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//name.setText("sysadmin"); 设置初始值
				final Handler myHandler = new Handler(){
					int i = 0;
					@Override
					public void handleMessage(Message msg) { //该线程位于主线程
						// TODO Auto-generated method stub
						//如果该消息是本程序所发送的
						if(msg.what == 0x1233){
							//主线程里面 显示操作
							i++;
							showToast("第"+i+"次连接开始....");
						}
					}
				};
				//定义一个计时器,让该计时器周期性的执行指定任务 TimerTask对象的本质就是启动一条新线程
				new Timer().schedule(new TimerTask()
				{
					@Override
					public void run() {
						//新启动的线程无法访问该Activity里的组件
						//所以需要通过Handler发送消息
						// TODO Auto-generated method stub
						Message msg = new Message();
						msg.what = 0x1233;
						//发送消息
						myHandler.sendMessage(msg);
						
						LOGIN_NAME = name.getText().toString();
						//在子线程里面发送请求 
						socketServer();
					}
				},0,10000);
				//
				/*// 压力测试 10s秒钟 执行一次
				while(true){
					new Thread(){
						public  void run(){
							socketServer();
						}
					}.start();
					try {
						Thread.sleep(10000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}*/
			}
		});
		System.out.println(1000);
	}


	public  void showToast(final String text) {
		  handler.post(new Runnable() {
		   @Override
		   public void run() {
		    Toast.makeText(getApplicationContext(), text,
		      Toast.LENGTH_SHORT).show();

		   }
		  });
	}

	public void socketServer() {
		// 创建一个非阻塞的客户端程序
		System.out.println(2);
		IoConnector connector = new NioSocketConnector();
		// 设置链接超时时间
		System.out.println(3);
		connector.setConnectTimeout(5);
		System.out.println(4);
		// 添加过滤器
		connector.getFilterChain().addLast(
				"codec",
				new ProtocolCodecFilter(new TextLineCodecFactory(Charset
						.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(),
						LineDelimiter.WINDOWS.getValue())));
		// 添加业务逻辑处理器类
		connector.setHandler(new Demo1ClientHandler());
		IoSession session = null;
		try {
			System.out.println(5);
			System.out.println(HOST + "|" + PORT);
			// 这里是异步操作 连接后立即返回
			ConnectFuture future = connector.connect(new InetSocketAddress(
					HOST, PORT));// 创建连接
			System.out.println(6);
			future.awaitUninterruptibly();// 等待连接创建完成 
			System.out.println(7);
			session = future.getSession();// 获得session
			// session.setAttribute(arg0, arg1)
			String jsonStr = "{\"people\":["
					+ "{ \"firstName\": \"问你t\", \"lastName\":\"McLaughlin\",\"email\": \"aaaa\" } ,"
					+ "{ \"firstName\": \"Brett\", \"lastName\":\"McLaughlin\",\"email\": \"aaaa\" } ,] } ";
			JSONObject json = createJSONObject();

			// 根据key返回一个字符串
			// //String username = json.getString("username");
			// System.out.println("username==>"+username);
			System.out.println(8);
			session.write(json);// 发送消息
			System.out.println(9);
			
			 session.getCloseFuture().awaitUninterruptibly();// 等待连接断开
			 connector.dispose();
			 System.out.println(Demo1ClientHandler.ini);
			 showToast(Demo1ClientHandler.ini);
		} catch (Exception e) {
			showToast("客户端链接异常,请检查网络");
			logger.error("客户端链接异常...", e);
		}
		
	}

	public static JSONObject createJSONObject() {
		JSONObject jsonObject = new JSONObject();
		try {
			jsonObject.put("username", LOGIN_NAME);
			jsonObject.put("sex", "男");
			jsonObject.put("QQ", "413425430");
			jsonObject.put("Min.score", new Integer(99));
			jsonObject.put("nickname", "梦中心境");
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return jsonObject;
	}
}
wangmiao 写道
这里客户端运用了 Handler消息的传递机制,主要是为了解决android应用的多线程问题--Android平台不允许Activity新启动的线程访问该Activity里的界面组件,这样就会导致新启动的线程无法改变界面组件的属性值。
Handler类的主要作用有两个:1.新启动的线程中发送消息 2.在线程中获取、处理消息
具体的关于Handler类的的使用去看相关的帮助说明。

 

  

 

逻辑处理:

package org.demo;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Demo1ClientHandler extends IoHandlerAdapter {
	private static Logger logger = LoggerFactory
			.getLogger(Demo1ClientHandler.class);

	static String ini = "";
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		System.out.println(message);
		System.out.println(11);
		String msg = message.toString();
		String info = "";
		if ("1".equals(msg)) {
			// session.close(); //用户登录成功 关闭连接
			info = "登录成功";
		} else {
			info = "登录失败";
		}
		ini = info;
		session.setAttribute("state", info);
		session.close();
		System.out.println(12);
	//	 final HelloWorld h = new HelloWorld();
		// h.DisplayToast(info);
		logger.info("客户端接收到的信息为:" + msg);
	}



	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {

		logger.error("客户端发生异常...", cause);
	}

	@Override
	public void sessionCreated(IoSession arg0) throws Exception {
		// TODO Auto-generated method stub
	}

	@Override
	public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
		// TODO Auto-generated method stub
	}

	/** 
	* 这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP 来 
	* 说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。 
	*/  
	@Override
	public void sessionOpened(IoSession arg0) throws Exception {
		logger.info("ok", "i am ready!");
		System.out.println(6);
	}
}

  

  • 大小: 22 KB
  • 大小: 23.1 KB
  • 大小: 21.2 KB
4
1
分享到:
评论
5 楼 枫尘01 2013-12-31  
可否发我一份demo楼主841347983@qq.com,我用你这个demo一直在客户端出现getSession()过不去出现链接问题。
4 楼 supericetea 2013-10-11  
楼主,能不能分享一下源码,993819762@qq.com
3 楼 yu1911802978 2012-12-31  
楼主,能否分享一下你的包啊?邮箱地址是1051988660@qq.com
2 楼 a82279597 2012-07-11  
楼主,你导入的是什么包啊。Android客服端的。能发我一份吗?a82279597@163.com或者直接我QQ82279597谢谢了。
1 楼 zhaoze87 2012-05-05  
不知道怎么回事,我加入mina,运行的时候总是报Conversion to Dalvik format failed with error 1
可否把你的mina包发我一份,zhaoze87@gmail.com,谢谢!

相关推荐

    基于Android开发MINA框架使用详解

    详细讲解如何使用MINA配合Android客户端实现聊天功能,解决中文乱码问题,解决Android客户端接收不到消息问题

    Mina框架在android上的使用范例

    如何使用mina框架简化android端TCP通信的开发

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

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

    apache-mina 即时通信框架,加入SSH和android包

    这个框架协议自己定义(即:底层已有字符串传输或Object传输,自己可以定义字符串会对象进行解析来制定自己的协议) 语音、图片等其实也是上传文件服务器再连个即时通信字符串通信而已; 注意:SSH-lib里有注意...

    Mina通信Demo

    Android手机端做服务器和客户端,使用MINA通信的demo,通过Demo可以清晰的看到Android平台使用Mina框架处理Socket通信的方法。

    MinaForAndroid:基于Mina的android通信框架,通过封装实现RPC通信,功能仍在完善中

    MinaForAndroid基于Mina的android通信框架,通过封装实现RPC通信,旨在打造一个如下功能的通信框架:1.可扩展的RPC通信,客户端和服务端之间可自定义通信接口(在此套用Android框架层的概念叫做service服务)。自定义...

    一款Android平台UDP双向通信源码

    本源码是《NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战》文中的代码,详见:http://www.52im.net/thread-388-1-1.html

    mina通信服务器端客户端源码.rar

    代码利用mina框架实现了服务器端和客户端,客户端的登录请求、客户端向服务器端请求图片文件的功能。代码分为服务端和客户端,开发环境eclipse。服务器代码可在web项目中使用,客户端代码可以在Android开发时使用,...

    Android网络通信的实现方式

    Android网络编程分为两种:基于http协议的,和基于socket的。...(3)Apache Mina框架 一、HttpURLConnection的实现方式 String response = null; Url url = new URL(path); HttpURLConnection connectio

    android聊天项目

    基于MINA框架的 UDP通信实现的简单 Android聊天项目,androi客户端是用原生方式写的。

    基于Netty的Android点对点聊天软件-源码

    基于Netty的Android点对点聊天软件-源码 Netty是基于NIO的JAVA异步通讯框架,比Mina在性能上更具有优势,其作者也正是Mina的原作者之一。

    JAVA上百实例源码以及开源项目源代码

     Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲区、写入数据到文件、关闭输入流、关闭套接字关闭输出流、输出错误信息等Java编程小技巧。 Java数组倒置...

    java开源包1

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包11

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包2

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包3

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包6

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包5

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包10

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

    java开源包4

    6、支持多种通信框架(Mina/Netty/Grizzly),支持多种序列化/反序列化(Java/Hessian/PB); 7、支持自定义通信协议,可完全替换NFS-RPC自带的协议。 淘宝开放平台JAVA版SDK top4java 设计原则 容易维护扩展(不...

Global site tag (gtag.js) - Google Analytics