热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JAVAANDROIDSOCKET通信检测(SERVER)连接是否断开

Pre解决思路代码后记:客户端app上的部分代码调用:服务器上:客户端判断服务器是否还活着代码:在利用socket写通讯程序的时候,想检测服务器是否还活着。从网上找了很多资料,都没
  • Pre
  • 解决思路
  • 代码后记:
    • 客户端app上的部分代码
    • 调用:
    • 服务器上:
    • 客户端判断服务器是否还活着代码:

在利用socket写通讯程序的时候,想检测服务器是否还活着。

从网上找了很多资料,都没有自己合适的,最后自己想了个办法,不过也相当于截取了心跳检测的一部分。

这里检测的是远程server的连接,而不是本地是否连接成功。首先想到socket类的方法isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等,但经过试验并查看相关文档,这些方法都是本地端的状态,无法判断远端是否已经断开连接。

而有一个方法sendUrgentData,查看文档后得知它会往输出流发送一个字节的数据,只要对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节。

或者,其实如果断开连接了,你发送过去的数据会收不到,最后client会抛出io异常。

但是,上面两个方法,抛出异常的时间长达15秒!简直不能忍。

解决思路

当然,这里的需求环境是:发送数据次数非常少,几乎只需要判断一两次,数据是集中发送的。那么,就可以这样了:

只要client在发送数据前,先发送自定义的一个测试数据,并自定义一个String之类的变量(初始值null)来接收server发回的数据,client发完测试数据,睡500毫秒(自定义时间)(异步接收服务器消息),然后立刻检测这个string是不是null,就可以知道server是否收到消息了。

代码

客户端APP上的部分代码


/**客户端线程,用来建立连接和发送消息 */
    public class Client implements Runnable{
        Socket s=null;
        DataInputStream dis=null;
        DataOutputStream dos=null;

        private boolean isCOnnected=false;
        Thread receiveMessage=null;
        /**发送消息
         * @param str 发送的信息,client仅向server发送两次消息,这是我自己的应用需求,根据实际情况来做你的。
         * @throws IOException 
         * */
        public void sendMessage(String str) throws IOException{
                dos.writeUTF(str);
                dos.flush();
        }

        /**断开连接*/
        public void disConnect(){
            try {
                dos.close();
                dis.close();
                s.close();
            } catch (IOException e) {
                System.out.println("client closed error");
                e.printStackTrace();
            }
        }
        /**建立socket连接,开启接收数据线程       * */
        public void run() {
            try {
                s=new Socket(SERVER_HOST_IP,SERVER_HOST_PORT);
                s.setOOBInline(true);
                dis=new DataInputStream(s.getInputStream());
                dos=new DataOutputStream(s.getOutputStream());
                System.out.println("connected!");
                isCOnnected=true;
                receiveMessage=new Thread(new ReceiveListenerThread());
                receiveMessage.start();
                //发送imei
                sendMessage(IMEI);
            } catch (UnknownHostException e) {
                System.out.println("fuwuqoweikaiqi");
                e.printStackTrace();
            } catch (IOException e) {
                System.out.println("ioerr");
                e.printStackTrace();
            }
        }

        private class ReceiveListenerThread implements Runnable{
        //这一部分接收数据的处理,请根据实际情况修改
            String data[]=new String[3];
            public void run() {
                    try {
                        if(isConnected){
                            String receivedMessage=dis.readUTF();
                            System.out.println(receivedMessage);
                            serverStarted=true;
                            data=receivedMessage.split("_");
                            isLegal=Integer.parseInt(data[0]);
                            num1=Integer.parseInt(data[1]);
                            num2=Integer.parseInt(data[2]);
                            System.out.println(""+isLegal+num1+""+num2);
                        }
                        if(isConnected){
                            finalOK=dis.readUTF();
                        }
                    }catch (SocketException e){
                        System.out.println("exit!");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }

        }

调用:

Client client=null;
/**客户端网络线程*/
Thread tClient=null;
client=new Client();
tClient=new Thread(client);
tClient.start();

服务器上:


/** 这是服务器用来接收处理客户端的线程类 */
    class Client implements Runnable {
        private Socket s;
        private DataInputStream dis = null;
        private DataOutputStream dos = null;
        private boolean isCOnnected= false;
        public Client(Socket s) {
            this.s = s;
            try {
                dis = new DataInputStream(s.getInputStream());
                dos = new DataOutputStream(s.getOutputStream());
                isCOnnected= true;
            } catch (IOException e) {
                System.out.println("on clients' data in and out have error");
                // e.printStackTrace();
            }
        }
        public void run() {
            String str;
            try {
                // 先检查是否是合法的客户端
                while (isConnected) {
                    str = dis.readUTF();
                        str = dis.readUTF();
                        //此处的具体代码省略
                        dos.writeUTF("ok");
                        dos.flush();
                    }
                }
            } catch (EOFException e) {
                System.out.println("Client closed");
                Home.appendMessage((legalNum + 1) + "号客户端已经登出");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (dis != null)
                        dis.close();
                    if (dos != null)
                        dos.close();
                    if (s != null)
                        s.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

客户端判断服务器是否还活着代码:

try {
    //客户端发送一个测试信息
        client.sendMessage(COOKIE);
        System.out.println("send");
        //睡1秒
        SystemClock.sleep(1000);
        //这个finalok是在客户端的接收线程那里处理的。如果不是null说明服务器没问题
        if(finalOK!=null){
            client.disConnect();
            exit("感谢您的使用,本次已经结束~"); 
        }else{
            throw new  IOException() ;
        }
        //超时检测
    } catch (IOException e) {
        new AlertDialog.Builder(MainActivity.this).setTitle("提示").setPositiveButton("好的", null).setMessage("服务器关闭了,请联系管理员并在服务器重新开启后再次点击【发送】来提交数据").show();
        client.disConnect();
        e.printStackTrace();
    }

后记:

当初只是简单记录了下自己的想法,写的很简陋,没想到慢慢这篇文章还好多人看,深感不安,故更新补充一下。

2015.3.27

声明:


文章若无说明转载,均为原创,如需转载,请注明出处!


推荐阅读
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
author-avatar
咪了眼的小迷糊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有