客户端与多服务端的TCP连接状态问题

问题表征:与device列表中两个或者以上的设备进行连接时,“已连接”的提示label显示不正确。当连上一个时,device列表的更新和连接状态显示正常;当连接第二个或者以上的设备时,连接状态全部显示全部断开。

每连接一个设备,都会启动三个新线程:thread1. tcp数据收发线程; thread2. 连接状态标志检测线程; thread3. 心跳包发送及检测线程。考虑到thread2将直接决定列表显示label的状态,因debug方式不当在thread2 和thread3 中瞎设置断点,发现当连接第二个设备的时候,thread3心跳包检测超时,于是将连接标志设置为fasle并退出了检测线程,thread2检测到连接状态标识的改变并广播至主活动将设备列表进行更新,于是显示连接断开。

于是乎一通断点跟踪,代码屏蔽打开,小修小改的尝试,终不知其因。忘了怎了眼一尖儿眸一亮发现heartbeats检测可能有问题,因为使用的是Handler.postDelay(),再一查,果然这并没有生成新的非UI线程[现在回看貌似也没问题,毕竟是在thread1中开启handler计时。如果该线程没有消息队列呢???(1):尝试未验证的解释——起初ClientTCP继承自Runnable,当在device中new ClientTCP的时候,实则在device所在的主活动声明定义了handler,于是handler使用的是MainActivity的消息队列] 果断改成了继承自Thread(其实这里又是一个曲折的过程,略去N字),一试,问题依旧存在,懵了。

迷雾主要还是笼罩在开启第二组连接线程的时候,这个过程到底发生了什么?多线程又该如何调试呢?刚开始想到的是打印输出至控制台,结果发现,当连接且仅连接一个设备的时候,心跳线程打印正常,但是当建立起第二个TCP连接的时候,之前开启的线程不再打印,而且新建的线程在打印四次左右(刚好是超时容忍Duration)也不再输出信息。这尼玛,奇了怪了,按理说线程是独立运行的吧,而且也没有共享数据。【1. handler.postDelay() 两个线程的显示状态同时改变; 2. 改成分离的线程后,连接先后掉线】于是想到当初查找ANR问题时,对/data/NAR/traces.txt的Log数据进行了分析,里边提供线程状态信息。于是尝试导出[发现平板未root没有导出权限,于是通过360一键Root进行刷机,本以为会等一段,没想几秒钟就搞定了],发现该文件一直为空…好吧,此路不通。

改空运。搜android多线程分析,从结果中跟着利用AS 自带的DDMS进行多线程跟踪,轻易发现:只连接一个tcp的时候,三个线程工作正常,但是打开第二个连接的时候,heartbeats检测线程却先后退出了。So why?Device里边有什么共享而不应的变量吗?于是打开相应的文件对不必要的static进行了一番地毯式清理,再一试,成功!

原因:socket被定义成static。当第一次建立连接的时候,ok,一切就绪,一切入轨。但是当建立第二个连接,因为socket的唯一性,之前的socket被关闭,重新new了一个socket。于是在超时时间过后,第一个连接的心跳检测退出并关闭了socket。又过了第二个超时时间,新连接的心跳线程也退出,并在尝试关闭socket的时候抛出关闭异常。


欢迎大家收看本期的《走近科学栏目》。为何峨眉山一古寺屋顶永远无树叶?为何一个村子夜里频传出叫?为何一个用了多年的牛皮鼓长出了牛毛?——经多方验证:风吹走的;一胖子打呼噜;做鼓的人当初没把毛打理干净……


你可能感兴趣的:(android,tcp,多线程,多连接)