android之mina框架通信学习
16lz
2021-01-24
这几天刚学期android,目前项目要求的客户端是android平台,所以要开始啃了....
服务器与客户端的通信准备使用现有的开发框架,找了几个----mina,google 的 protobuf,smack,androidpn,Netty...
这些框架都不错,不过最终选择的是apache的mina框架,主要是mina在网上的资料比较全,用的也比较广泛,再就是也适合我项目以后的扩展加入SPRING\CXF\RESTFUL WEBSERVICE等
不废话了,开始把目前学习的进度开始进行整理,方便自己以后进行查阅,也给其他入门的兄弟们 参考参考。
当然,最重要的是希望大家能够提出并给与宝贵的经验。
服务端代码:
Java代码- packageorg.demo;
- importjava.net.InetSocketAddress;
- importjava.nio.charset.Charset;
- importorg.apache.mina.common.IdleStatus;
- importorg.apache.mina.common.IoAcceptor;
- importorg.apache.mina.filter.codec.ProtocolCodecFilter;
- importorg.apache.mina.filter.codec.textline.LineDelimiter;
- importorg.apache.mina.filter.codec.textline.TextLineCodecFactory;
- importorg.apache.mina.transport.socket.nio.NioSocketAcceptor;
- importorg.slf4j.Logger;
- importorg.slf4j.LoggerFactory;
- publicclassDemo1Server{
- privatestaticLoggerlogger=LoggerFactory.getLogger(Demo1Server.class);
- privatestaticintPORT=8989;
- publicstaticvoidmain(String[]args){
- IoAcceptoracceptor=null;
- try{
- //创建一个非阻塞的server端的Socket
- acceptor=newNioSocketAcceptor();
- //设置过滤器(使用Mina提供的文本换行符编解码器)
- acceptor.getFilterChain().addLast(
- "codec",
- newProtocolCodecFilter(newTextLineCodecFactory(Charset
- .forName("UTF-8"),
- LineDelimiter.WINDOWS.getValue(),
- LineDelimiter.WINDOWS.getValue())));
- //设置读取数据的缓冲区大小
- acceptor.getSessionConfig().setReadBufferSize(2048);
- //读写通道10秒内无操作进入空闲状态
- acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,10);
- //绑定逻辑处理器
- acceptor.setHandler(newDemo1ServerHandler());
- //绑定端口
- acceptor.bind(newInetSocketAddress(PORT));
- logger.info("服务端启动成功...端口号为:"+PORT);
- }catch(Exceptione){
- logger.error("服务端启动异常....",e);
- e.printStackTrace();
- }
- }
- }
逻辑处理:
Java代码- packageorg.demo;
- importjava.util.Date;
- importnet.sf.json.JSONObject;
- importorg.apache.mina.common.IdleStatus;
- importorg.apache.mina.common.IoHandlerAdapter;
- importorg.apache.mina.common.IoProcessor;
- importorg.apache.mina.common.IoSession;
- importorg.apache.mina.transport.socket.nio.NioProcessor;
- importorg.slf4j.Logger;
- importorg.slf4j.LoggerFactory;
- publicclassDemo1ServerHandlerextendsIoHandlerAdapter{
- publicstaticLoggerlogger=LoggerFactory.getLogger(Demo1ServerHandler.class);
- /**
- *这个方法当一个Session对象被创建的时候被调用。对于TCP连接来说,连接被接受的时候
- *调用,但要注意此时TCP连接并未建立,此方法仅代表字面含义,也就是连接的对象
- *IoSession被创建完毕的时候,回调这个方法。
- *对于UDP来说,当有数据包收到的时候回调这个方法,因为UDP是无连接的。
- */
- @Override
- publicvoidsessionCreated(IoSessionsession)throwsException{
- logger.info("服务端与客户端创建连接...");
- }
- /**
- *这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP来
- *说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。
- */
- @Override
- publicvoidsessionOpened(IoSessionsession)throwsException{
- logger.info("服务端与客户端连接打开...");
- }
- /**
- *接收到消息时调用的方法,也就是用于接收消息的方法,一般情况下,message是一个
- *IoBuffer类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。
- */
- @Override
- publicvoidmessageReceived(IoSessionsession,Objectmessage)
- throwsException{
- /*
- Stringmsg=message.toString();
- //读取数据
- logger.info("服务端接收到的数据为:"+msg+"客户端ip:"+session.getLocalAddress());
- if("bye".equals(msg)){//服务端断开连接的条件
- session.close();
- }
- Datedate=newDate();
- session.write(date);*/
- JSONObjectjsonObject=JSONObject.fromObject(message.toString());
- Stringusername;
- Stringsex;
- Stringqq;
- Stringscore;
- Stringnickname;
- username=jsonObject.getString("username");
- sex=jsonObject.getString("sex");
- qq=jsonObject.getString("QQ");
- score=jsonObject.getString("Min.score");
- nickname=jsonObject.getString("nickname");
- intstate=login(username);
- Stringmsg="登录成功!";
- if(state==0){
- msg="登录失败!";
- }
- logger.info("用户:"+username+msg);
- //模拟登陆
- if("bye".equals(nickname)){//服务端断开连接的条件
- session.close();
- }
- //Datedate=newDate();
- session.write(state);
- }
- //验证用户名与密码
- publicintlogin(Stringmessage){
- if("sysadmin".equals(message)){
- return1;
- }
- return0;
- }
- /**
- *当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后,
- *也就是说发送消息是不能用这个方法的。
- */
- @Override
- publicvoidmessageSent(IoSessionsession,Objectmessage)throwsException{
- logger.info("服务端发送信息成功...");
- }
- /**
- *对于TCP来说,连接被关闭时,调用这个方法。
- *对于UDP来说,IoSession的close()方法被调用时才会毁掉这个方法。
- */
- @Override
- publicvoidsessionClosed(IoSessionsession)throwsException{
- logger.info("服务端连接已经失效");
- }
- /**
- *这个方法在IoSession的通道进入空闲状态时调用,对于UDP协议来说,这个方法始终不会
- *被调用。
- */
- @Override
- publicvoidsessionIdle(IoSessionsession,IdleStatusstatus)
- throwsException{
- logger.info("服务端进入空闲状态...");
- }
- /**
- *这个方法在你的程序、Mina自身出现异常时回调,一般这里是关闭IoSession。
- */
- @Override
- publicvoidexceptionCaught(IoSessionsession,Throwablecause)
- throwsException{
- logger.error("服务端发送异常...",cause);
- }
- }
客户端代码:
Java代码- packageorg.demo;
- importjava.net.InetSocketAddress;
- importjava.nio.charset.Charset;
- importjava.util.Timer;
- importjava.util.TimerTask;
- importorg.apache.mina.common.ConnectFuture;
- importorg.apache.mina.common.IoConnector;
- importorg.apache.mina.common.IoSession;
- importorg.apache.mina.filter.codec.ProtocolCodecFilter;
- importorg.apache.mina.filter.codec.textline.LineDelimiter;
- importorg.apache.mina.filter.codec.textline.TextLineCodecFactory;
- importorg.apache.mina.transport.socket.nio.NioSocketConnector;
- importorg.json.JSONException;
- importorg.json.JSONObject;
- importorg.slf4j.Logger;
- importorg.slf4j.LoggerFactory;
- importandroid.app.Activity;
- importandroid.content.Context;
- importandroid.os.Bundle;
- importandroid.os.Handler;
- importandroid.os.HandlerThread;
- importandroid.os.Message;
- importandroid.view.View;
- importandroid.view.View.OnClickListener;
- importandroid.widget.Button;
- importandroid.widget.EditText;
- importandroid.widget.Toast;
- /**
- *@authorwangmiao
- *@version创建时间:2012-4-24下午10:57:53简单说明
- */
- publicclassHelloWorld2extendsActivity{
- privatestaticLoggerlogger=LoggerFactory.getLogger(HelloWorld2.class);
- privatestaticStringHOST="192.168.1.100";
- privatestaticintPORT=8989;
- privatestaticStringLOGIN_NAME="";
- publicHelloWorld2(){
- }
- Handlerhandler=newHandler();
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- //TODOAuto-generatedmethodstub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- System.out.println(1);
- /*
- *newThread(){publicvoidrun(){socketServer();}}.start();
- */
- Buttonbtn=(Button)findViewById(R.id.button1);
- btn.setOnClickListener(newOnClickListener(){
- EditTextname=(EditText)findViewById(R.id.username);
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- //name.setText("sysadmin");设置初始值
- finalHandlermyHandler=newHandler(){
- inti=0;
- @Override
- publicvoidhandleMessage(Messagemsg){//该线程位于主线程
- //TODOAuto-generatedmethodstub
- //如果该消息是本程序所发送的
- if(msg.what==0x1233){
- //主线程里面显示操作
- i++;
- showToast("第"+i+"次连接开始....");
- }
- }
- };
- //定义一个计时器,让该计时器周期性的执行指定任务TimerTask对象的本质就是启动一条新线程
- newTimer().schedule(newTimerTask()
- {
- @Override
- publicvoidrun(){
- //新启动的线程无法访问该Activity里的组件
- //所以需要通过Handler发送消息
- //TODOAuto-generatedmethodstub
- Messagemsg=newMessage();
- msg.what=0x1233;
- //发送消息
- myHandler.sendMessage(msg);
- LOGIN_NAME=name.getText().toString();
- //在子线程里面发送请求
- socketServer();
- }
- },0,10000);
- //
- /*//压力测试10s秒钟执行一次
- while(true){
- newThread(){
- publicvoidrun(){
- socketServer();
- }
- }.start();
- try{
- Thread.sleep(10000);
- }catch(InterruptedExceptione){
- //TODOAuto-generatedcatchblock
- e.printStackTrace();
- }
- }*/
- }
- });
- System.out.println(1000);
- }
- publicvoidshowToast(finalStringtext){
- handler.post(newRunnable(){
- @Override
- publicvoidrun(){
- Toast.makeText(getApplicationContext(),text,
- Toast.LENGTH_SHORT).show();
- }
- });
- }
- publicvoidsocketServer(){
- //创建一个非阻塞的客户端程序
- System.out.println(2);
- IoConnectorconnector=newNioSocketConnector();
- //设置链接超时时间
- System.out.println(3);
- connector.setConnectTimeout(5);
- System.out.println(4);
- //添加过滤器
- connector.getFilterChain().addLast(
- "codec",
- newProtocolCodecFilter(newTextLineCodecFactory(Charset
- .forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),
- LineDelimiter.WINDOWS.getValue())));
- //添加业务逻辑处理器类
- connector.setHandler(newDemo1ClientHandler());
- IoSessionsession=null;
- try{
- System.out.println(5);
- System.out.println(HOST+"|"+PORT);
- //这里是异步操作连接后立即返回
- ConnectFuturefuture=connector.connect(newInetSocketAddress(
- HOST,PORT));//创建连接
- System.out.println(6);
- future.awaitUninterruptibly();//等待连接创建完成
- System.out.println(7);
- session=future.getSession();//获得session
- //session.setAttribute(arg0,arg1)
- StringjsonStr="{\"people\":["
- +"{\"firstName\":\"问你t\",\"lastName\":\"McLaughlin\",\"email\":\"aaaa\"},"
- +"{\"firstName\":\"Brett\",\"lastName\":\"McLaughlin\",\"email\":\"aaaa\"},]}";
- JSONObjectjson=createJSONObject();
- //根据key返回一个字符串
- ////Stringusername=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(Exceptione){
- showToast("客户端链接异常,请检查网络");
- logger.error("客户端链接异常...",e);
- }
- }
- publicstaticJSONObjectcreateJSONObject(){
- JSONObjectjsonObject=newJSONObject();
- try{
- jsonObject.put("username",LOGIN_NAME);
- jsonObject.put("sex","男");
- jsonObject.put("QQ","413425430");
- jsonObject.put("Min.score",newInteger(99));
- jsonObject.put("nickname","梦中心境");
- }catch(JSONExceptione){
- //TODOAuto-generatedcatchblock
- e.printStackTrace();
- }
- returnjsonObject;
- }
- }
Handler类的主要作用有两个:1.新启动的线程中发送消息 2.在线程中获取、处理消息
具体的关于Handler类的的使用去看相关的帮助说明。
逻辑处理:
Java代码- packageorg.demo;
- importorg.apache.mina.common.IdleStatus;
- importorg.apache.mina.common.IoHandlerAdapter;
- importorg.apache.mina.common.IoSession;
- importorg.slf4j.Logger;
- importorg.slf4j.LoggerFactory;
- publicclassDemo1ClientHandlerextendsIoHandlerAdapter{
- privatestaticLoggerlogger=LoggerFactory
- .getLogger(Demo1ClientHandler.class);
- staticStringini="";
- @Override
- publicvoidmessageReceived(IoSessionsession,Objectmessage)
- throwsException{
- System.out.println(message);
- System.out.println(11);
- Stringmsg=message.toString();
- Stringinfo="";
- if("1".equals(msg)){
- //session.close();//用户登录成功关闭连接
- info="登录成功";
- }else{
- info="登录失败";
- }
- ini=info;
- session.setAttribute("state",info);
- session.close();
- System.out.println(12);
- //finalHelloWorldh=newHelloWorld();
- //h.DisplayToast(info);
- logger.info("客户端接收到的信息为:"+msg);
- }
- @Override
- publicvoidexceptionCaught(IoSessionsession,Throwablecause)
- throwsException{
- logger.error("客户端发生异常...",cause);
- }
- @Override
- publicvoidsessionCreated(IoSessionarg0)throwsException{
- //TODOAuto-generatedmethodstub
- }
- @Override
- publicvoidsessionIdle(IoSessionarg0,IdleStatusarg1)throwsException{
- //TODOAuto-generatedmethodstub
- }
- /**
- *这个方法在连接被打开时调用,它总是在sessionCreated()方法之后被调用。对于TCP来
- *说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。
- */
- @Override
- publicvoidsessionOpened(IoSessionarg0)throwsException{
- logger.info("ok","iamready!");
- System.out.println(6);
- }
- }
更多相关文章
- Android开发之Java设计模式基础篇
- android reboot 功能的添加
- React-Native:调用(Android)Native方法
- Android(安卓)UI开发 View自绘控件 分享
- Android(安卓)Activity之间切换出现短暂黑屏的处理方法
- android横竖屏切换(复制未整理)
- Android大图加载方法
- android 自定义View之SubmitView
- Android(安卓)开发杂记