【问题标题】:How to check if client has disconnected? [duplicate]如何检查客户端是否已断开连接? [复制]
【发布时间】:2013-07-27 00:09:28
【问题描述】:

我有一个带有 Socket 的 java 程序。我需要检查客户端是否已断开连接。我需要一个如何做到这一点的例子。我研究过,但我不明白。那么有人可以制作示例代码并解释所有内容吗?

抱歉英语不好 我的代码:

    package proov_server;

//SERVER 2
import java.io.*;
import java.net.*;

class server2 {
    InetAddress[] kasutaja_aadress = new InetAddress[1000];
    String newLine = System.getProperty("line.separator");
    int kliendiNr = 0;
    int kilene_kokku;
  server2(int port) {

    try {

      ServerSocket severi_pistik = new ServerSocket(port);
        System.out.println("Server töötab ja kuulab porti " + port + ".");


      while (true) {

        Socket pistik = severi_pistik.accept();
        kliendiNr++;

        kasutaja_aadress[kliendiNr] = pistik.getInetAddress();
        System.out.println(newLine+"Klient " + kliendiNr + " masinast "
                      + kasutaja_aadress[kliendiNr].getHostName() + " (IP:"
                      + kasutaja_aadress[kliendiNr].getHostAddress() + ")");

        // uue kliendi lõime loomine
        KliendiLoim klient = new KliendiLoim(pistik,kliendiNr);

        // kliendi lõime käivitamine
        klient.start();

      }
    }
    catch (Exception e) {
      System.out.println("Serveri erind: " + e);
    }
  }

  DataOutputStream[] väljund = new DataOutputStream[1000];
  DataInputStream[] sisend = new DataInputStream[1000];

  int klient = 0;
  int nr;
  // sisemine klass ühendusega tegelemiseks
      class KliendiLoim extends Thread {

        // kliendi pistik

      Socket pistik;
        // kliendi number


        KliendiLoim(Socket pistik2,int kliendiNr) {
          nr = kliendiNr;
          this.pistik = pistik2;

        }
        public boolean kontroll(){
            try{
                System.out.println("con "+pistik.isConnected());
                System.out.println("close "+pistik.isClosed());
                if(pistik.isConnected() &&  !pistik.isClosed()){
                    //System.out.print(con_klient);
                    return true;

                }
            }catch(NullPointerException a){
                System.out.println("Sihukest klienti pole!!!");

            }
            kliendiNr --;
            return false;

        }

        public void run() {
              try { 
                    sisend[nr] = new DataInputStream(pistik.getInputStream()); //sisend
                    väljund[nr] = new DataOutputStream(pistik.getOutputStream()); //väljund 
              }catch (Exception ea) {
                    System.out.println(" Tekkis erind: " + ea);
              }   
              while(true){
                      try{


                        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

                        System.out.print("Sisesta k2sk: ");
                        String k2sk = null;
                        k2sk = br.readLine();
                        /*
                        String command;
                        if(k2sk.indexOf(" ") < 0){
                            command = k2sk;
                        }else{
                            command = k2sk.substring(0, k2sk.indexOf(" "));
                        }
                        */
                        String[] words = k2sk.split("\\s+");
                        for (int i = 0; i < words.length; i++) {
                            words[i] = words[i].replaceAll(" ", "");
                        }
                        switch(words[0]){
                        case "suhtle":

                            if(väljund.length > klient && väljund[klient] != null)
                            {
                                väljund[klient].writeUTF("1");


                            }else{
                                väljund[klient] = null;
                                sisend[klient] = null;
                                System.out.println("Sihukest klienti pole");
                            }
                        break;
                        case "vaheta":
                            try{
                                int klinetnr = Integer.parseInt(words[1]);
                                //if(kontroll(klinetnr) ){
                                    klient = Integer.parseInt(words[1]);
                                //}
                            }
                            catch(NumberFormatException e){
                                System.out.println("See pole number!!! ");
                            }
                        break;

                        case "kliendid":
                            if(kliendiNr != 0){
                                for(int i=1;i <= kliendiNr;i++){
                                    if(kontroll()){
                                        System.out.println("Klient:"+i+" ip: " + kasutaja_aadress[i] );
                                    }else{
                                        System.out.println("Pisi");
                                        väljund[klient] = null;
                                        sisend[klient] = null;
                                    }
                                }
                                System.out.println(newLine);
                            }else{
                                System.out.println("Kiente pole");
                            }
                        break;

                        }
                      System.out.println(kliendiNr);
                    }catch(SocketException a){
                        System.out.println("Klient kadus");

                    }
                    catch(Exception e){
                         System.out.println(" Viga: " + e);
                    }

          }
        }



  }
  public static void main(String[] args) {
        new server2(4321);

  }
}

【问题讨论】:

  • 您能否提供一些您的代码以便我们提供帮助!
  • 我复制粘贴了。我是java新手
  • 代码很多,有些变量名不是英文的。我建议你翻译其中的一些,这样更容易阅读。这不是义务,但可以提供帮助。
  • Socket Documentation 中有一些对我来说很有希望的方法。比如 isClosed 和 isConnected。也许这可能是一个开始?
  • @Marc-Andre 不。他们告诉你套接字的状态,而不是连接。

标签: java


【解决方案1】:

如果客户端已正确断开连接:

  • read() 将返回 -1
  • readLine() 返回 null
  • readXXX() 用于任何其他 X 抛出 EOFException。

检测 TCP 连接丢失的唯一真正可靠的方法是写入它。最终这将抛出一个IOException: connection reset,但由于缓冲,它至少需要两次写入。

【讨论】:

    【解决方案2】:

    Stackoverflow here 上的相关线程以及解决方案。基本上,该解决方案表示检测客户端-服务器断开连接的最佳方法是尝试从套接字读取。如果读取成功,则连接处于活动状态。如果在读取过程中抛出异常,则客户端和服务器之间没有连接。或者,可能会为套接字配置一个超时值以完成读取操作。如果超过此超时,则会抛出套接字超时异常,这可以被认为是客户端断开连接或网络关闭。

    这篇文章还谈到了使用 isReachable 方法 - 请参阅 InetAddress documentation。然而,这个方法只告诉我们远程主机是否可达。这可能只是客户端与服务器断开连接的一个原因。使用此技术,您将无法检测到由于客户端崩溃或终止而导致的断开连接。

    【讨论】:

    • 我想知道如果socket连接了但是没有什么可以读取,会发生什么?
    • 我对答案做了一个小的更正 - 如果套接字已连接并且没有可读取的内容,那么不会引发异常并且程序只是继续执行下一行。只有当套接字断开连接时,从套接字读取才会导致异常。
    • 这不正确。如果您在阻塞模式下设置了读取超时并且没有数据,您将收到 SocketTimeoutException。由您决定这是否意味着对等方处于非活动状态或网络已关闭。您引用的帖子中的答案质量非常低。
    • @EJP 感谢您的评论 - 我将您的注释合并到我的答案中。上面发布的线程中接受的答案对我来说似乎是一个合理的答案。但是,请使用任何更简单的技术来解决此问题来更新此线程
    • 失去可达性不会导​​致对等方断开连接。它可能会断开连接,但这不是一回事。超时异常也不等同于对等断开连接。检测客户端断开连接的最佳方法是读取并获取流的结尾,但检测断开连接的最佳方法是对其进行写入。同样,这些不是一回事。问题是关于对等断开连接,而不是连接断开,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 2018-06-11
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多