Java 如何使用后台线程检查套接字是否已连接

Java 如何使用后台线程检查套接字是否已连接,java,android,sockets,Java,Android,Sockets,我正在开发一个应用程序,在这个应用程序中,我在读写套接字之前检查端口的可用性。我使用以下代码检查状态 private boolean isAvailable(String host, int port) { try { Socket socket = new Socket(); socket.connect(new InetSocketAddress(host, port), 1000); isPortAva

我正在开发一个应用程序,在这个应用程序中,我在读写套接字之前检查端口的可用性。我使用以下代码检查状态

private boolean isAvailable(String host, int port) {
        try {
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(host, port), 1000);
            isPortAvailable = socket.isConnected();
        } catch (IOException e) {
            isPortAvailable = false;
        }
        return isPortAvailable;
    }
在此之后,我将在
onClick()上检查此状态

但我的问题是,如果我在主线程上检查此状态,那么android将给我
networkonMainThradException
那么我如何使用后台线程管理此操作?

如下所示:

private class CheckAvailabilityTask extends AsyncTask<Void, Void, Boolean> {
    String ip;
    int port;

    public CheckAvailabilityTask(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }
    @Override
    protected Boolean doInBackground(Void... params) {
        return isAvailable(this.ip, this.port);
    }

    @Override
    protected void onPostExecute(Boolean isAvailable) {
        if (iisAvailable) {
            startActivity(new Intent(getApplicationContext(),ActivityLivingRoom.class));
        } else
        Toast.makeText(getApplicationContext(),"Connection Error !", Toast.LENGTH_SHORT).show();
    }
}

我认为最好的解决方案是,在click事件上启动一个新线程,并将启动活动代码放在同一个线程中

如果您使用的是toast,您可以从该线程执行,但如果您计划更新UI(如红色/绿色状态),则必须使用处理程序和消息

仅供参考,Asynctask只是删除了线程的实现,并向人们展示了一个很好的抽象

试试这个

 private class SocketCheckTask extends AsyncTask<String , Integer , Boolean> {
       String classname="";
     public SocketCheckTask (String classname) {
              this.classname=classname;
    } 
@Override
protected Boolean doInBackground(String... params) {
    return isAvailable(params[0], Integer.parseInt(params[1]);
  }

@Override
protected void onPostExecute(Boolean isAvailable) {
   if (isAvailable)) {
     Class c=Class.forName("yourpackage"+classname);
startActivity(new Intent(getApplicationContext(),c));
     } else
Toast.makeText(getApplicationContext(),"Connection Error !", Toast.LENGTH_SHORT).show();
     }
}

您不能仅仅为了确定主机:端口是否可用而打开或关闭套接字

测试是否有任何服务或资源可用的唯一真正方法是尝试使用它

只需在需要时执行连接和I/O,并在此时处理产生的异常。无论如何,你必须抓住他们



不要编写试图预测未来的代码。

你不能使用AsyncTask或单独的线程吗?@Pragnani,我如何像使用返回布尔值的方法一样使用AsyncTask?获取一个布尔字段,并为其分配一个由doinBackground中的IsAvailable方法返回的值。这有什么错。。让我知道。?@Pragnani但在每次点击按钮时,我都以该方法传递不同的IP,我如何使用AsynckTask管理此问题?请检查我的答案……应该是这样的work@Thanks但是我想对多个按钮进行检查,那么在这个任务中我应该在哪里传递我的ip呢?这个类给了我类似于
的错误,返回类型与AsyncTask不兼容
检查我的更新答案,doInbackground应该返回Boolean,在返回字符串之前,Hanks,但我仍然对一件事感到困惑,我不想每次打开
ActivityLivingRoom.class
activity,这也应该改变你这是什么意思?您可以创建一个单独的类CheckAvailabilityTask,并从任何其他活动调用它requireds@Waqas他可能希望asynctask作为单独的类,而不是内部类class@thanks但我仍然对一件事感到困惑,因为ip chages启动活动也会发生变化,我不想每次打开
ActivityLivingRoom.class
activity我如何从
AsynkTask的
postExecute()
方法调用
startActivity()
方法?@juned为什么你认为你不能。。?我已经在答案检查中给出了我的意思是,如果我使用单独的
AsynkTask
classAsyctask是为更新UI而设计的,我看不到你在任何地方更新UI。但你肯定可以使用Asynctask。事实上,我想在开始执行套接字i/O的活动之前检查连接是否可用。这正是我刚才告诉你不要做的。您应该做的是(a)尝试连接和(b)尝试读取或写入。没有“连接可用”这样的概念。你的代码实际上是创建一个套接字,然后扔掉它。这没有任何意义。我明白你的意思了,谢谢,但我还是想知道有没有其他方法可以知道插座是打开的还是关闭的?@juned这个问题模棱两可。如果
Socket.isClosed()
返回false,则套接字打开。这会告诉你是否曾经关闭过插座。然而,这个套接字和对等方的套接字之间的连接可以处于任何状态,在TCP中,您可以找到的唯一方法是向它写入或从中读取。这里没有API。@downvoter欢迎您的评论:但是,您无法解释的downvote并不比单纯的站点破坏好多少。如果你对答案有不同意见,那就说出来吧。
new CheckAvailabilityTask(IP, PORT).execute();
 private class SocketCheckTask extends AsyncTask<String , Integer , Boolean> {
       String classname="";
     public SocketCheckTask (String classname) {
              this.classname=classname;
    } 
@Override
protected Boolean doInBackground(String... params) {
    return isAvailable(params[0], Integer.parseInt(params[1]);
  }

@Override
protected void onPostExecute(Boolean isAvailable) {
   if (isAvailable)) {
     Class c=Class.forName("yourpackage"+classname);
startActivity(new Intent(getApplicationContext(),c));
     } else
Toast.makeText(getApplicationContext(),"Connection Error !", Toast.LENGTH_SHORT).show();
     }
}
 SocketCheckTask task=new SocketCheckTask ("ActivityLivingRoom");
task.execute(ipadress,port);