第6章2节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-获取命令字串

从上一节的描述可以知道,MonkeyRunner发送给Monkey的命令是以字符串的形式交互的,那么事件处理的第一步当然是先去获得MonkeyRunner发送过来的字串命令了。

在事件源MonkeySourceNetwork初始化的时候构造函数会创建一个ServerSocket来监听来自客户端的链接和数据,但这个时候客户端并不能真正实现和服务端通信,因为该ServerSocket尚处于阻塞状态。既然ServerSocket是MonkeySourceNetwork的构造函数创建的,那么建立通信的又是哪个方法呢?真正的通信又是什么时候开始建立呢?

这里我们先回答第一个问题,建立通信是由MonkeySourceNetwork的私有成员方法startServer来处理的:

569   private void startServer()
570     throws IOException
571   {
572     this.clientSocket = this.serverSocket.accept();
...
577     MonkeySourceNetworkViews.setup();
578 
579     wake();
580 
581     this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
582 
583     this.output = new PrintWriter(this.clientSocket.getOutputStream(), true);
584   }
代码6-2-1 MonkeySourceNetwork - startServer

  • 572行: 通过调用serverSocket的accept方法来建立一个与客户端连接的Socket通信通道,并把该Socket实例赋予给clientSocket,往下会通过操作这个Socket实例来和客户端交互
  • 581行: 初始化从clientSocket读取数据的BufferedReader实例并赋予给input成员变量,往后的代码只需要调用input的readline方法就能获得一行命令字串数据
  • 583行: 初始化往clientSocket打印输出的PrintWriter实例并赋予给output成员变量,往后的代码只需要调用output的print或者println之类的方法就能往客户端传送数据

回答完第一个问题后,我们跟着看第二个问题,什么时候开始建立通信的?其实这个问题到了现在可以替换成:startServer是谁触发调用的。是从Monkey类的循环执行事件方法runMonkeyCyles调用mEventSource.getNextEvent开始触发的。上一章已经分析过这里的mEventSource是被初始化成MonkeySourceNetwork,因为Monkey是通过MonkeyRunner发送的命令”monkey --port 12345”来启动的。那么我们进入MonkeySourceNetwork的getNextEvent方法:

682   public MonkeyEvent getNextEvent()
683   {
684     if (!this.started) {
685       try {
686         startServer();
687       } catch (IOException e) {
688         Log.e("MonkeyStub", "Got IOException from server", e);
689         return null;
690       }
691       this.started = true;
692     }
...
696     try
697     {
698       for (;;)
699       {
700         MonkeyEvent queuedEvent = this.commandQueue.getNextQueuedEvent();
701         if (queuedEvent != null)
702         {
703           return queuedEvent;
704         }
...
709         if (deferredReturn != null) {
710           Log.d("MonkeyStub", "Waiting for event");
711           MonkeyCommandReturn ret = deferredReturn.waitForEvent();
712           deferredReturn = null;
713           handleReturn(ret);
714         }
715 
716         String command = this.input.readLine();
717         if (command == null) {
718           Log.d("MonkeyStub", "Connection dropped.");
719 
720 
721           command = "done";
722         }
723 
724         if ("done".equals(command))
725         {
726           try {
727             stopServer();
728           } catch (IOException e) {
729             Log.e("MonkeyStub", "Got IOException shutting down!", e);
730             return null;
731           }
732 
733 
734           return new MonkeyNoopEvent();
735         }
736 
737 
738         if ("quit".equals(command))
739         {
740           Log.d("MonkeyStub", "Quit requested");
741 
742           returnOk();
743           return null;
744         }
...
748 
749         if (!command.startsWith("#"))
750         {
...
755           translateCommand(command);
756         }
757       }
758 
759       return null;
760     }
761     catch (IOException e)
762     {
763       Log.e("MonkeyStub", "Exception: ", e);
764     }
765   }
代码6-2-2 MonkeySourceNetwork - getNextEvent

  • 684-687行: 如果在此之前还没有建立和客户端的通信的话,那么调用startServer方法来建立通信
  • 691行: 把通信状态保存下来。下次调用getNextEvent获取命令字串时就会在684行判断通信是否已经建立,是的话就会使用既有的通信,而不会创建新的Socket通信了
  • 698行: 进入一个无限循环,直到获取到一个事件位置
  • 700-703行: 如果命令队列中还有事件没有处理的话,从命令队列中取得一个事件返回
  • 716行: 通过调用上面提到的input的readline方法获得一个MonkeyRunner客户端发送过来的命令字串
  • 724-728行: 判断如果MonkeyRunner发送过来的命令字串是”done”的话,关闭与客户端的Socket通信
  • 738-744行: 判断如果MonkeyRunner发送过来的命令字串是”quit”的话,直接退出循环
  • 749-756行: 判断如果MonkeyRunner发送过来的命令字串不是上面两种情况,且不是以”#”号开始的话,调用MonkeySourceNetwork的translateCommand来进行往下的命令字串的解析翻译处理工作

注:更多文章请关注公众号:techgogogo或个人博客http://techgogogo.com。当然,也非常欢迎您直接微信(zhubaitian1)勾搭。本文由天地会珠海分舵原创。转载请自觉,是否投诉维权看心情。





  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值