中断连接插座

时间:2011-03-22 17:22:22

标签: java multithreading sockets nonblocking

我有一个GUI,其中包含要连接的服务器列表。如果用户单击它连接到它的服务器。如果用户单击第二个服务器,它将断开第一个服务器并连接到第二个服务器。每个新连接都在一个新线程中运行,以便程序可以执行其他任务。

但是,如果用户在第一台服务器仍在连接时单击第二台服务器,则会有两个同时连接。

我正在使用此连接,而connect()是阻止的行:

Socket socket = new Socket();
socket.connect(socketAddress, connectTimeout);

我想也许Thread.currentThread().interrupt();可行,但没有。

我是否需要稍微重构我的代码以便继续进行第一次连接,但是之后会立即关闭它?或者实际上有一种方法可以中断连接方法。

4 个答案:

答案 0 :(得分:2)

如果使用阻塞套接字实现,则中断线程将不会“取消”或中断套接字连接。打破“阻塞调用”的唯一方法是“关闭”套接字。您可以在Runnable任务(例如cancel)上公开一个关闭套接字的方法,并在用户尝试连接到第二个服务器时清理资源。

如果你想要,你可以有一个look at my throwaway attempt来打断阻塞调用的线程。

答案 1 :(得分:1)

您可以使用非阻塞套接字吗?我不是Java专家,但看起来SocketChannel是他们的非阻塞套接字类。

以下是一个例子:

// Create a non-blocking socket and check for connections
try {
    // Create a non-blocking socket channel on port 80
    SocketChannel sChannel = createSocketChannel("hostname.com", 80);

    // Before the socket is usable, the connection must be completed
    // by calling finishConnect(), which is non-blocking
    while (!sChannel.finishConnect()) {
        // Do something else
    }
    // Socket channel is now ready to use
} catch (IOException e) {
}

从这里采取: http://www.exampledepot.com/egs/java.nio/NbClientSocket.html

在while循环中,您可以检查一些需要取消和拯救的共享通知,然后关闭SocketChannel。

答案 2 :(得分:1)

我尝试了建议的答案,但没有任何对我有用。 所以我所做的是,不是将连接超时设置为10秒,而是尝试连续连接5次,连接超时为2秒。 我还声明了一个全局变量boolean cancelConnection

每次抛出超时异常时,我都可以根据cancelConnection的值进行分解或继续循环。

这是我正在编写的Android应用程序的代码片段:

try {
    SocketAddress socketaddres = new InetSocketAddress(server.ip,server.port);
    int max=5;
    for (int i = 1; i<=max; i++) {
        try {
            socket = new Socket();
            socket.connect(socketaddres, 2000);
            break;
        } catch (Exception e) {
            Log.d(TAG, "attempt "+i+ " failed");
            if (cancelConnection) {
                Log.d(TAG, "cancelling connection");
                throw new Exception();
            } else if (i==max) {
                throw new Exception();
            }
        }
    }
} catch (Exception e) {
    if (cancelConnection) {
            // Do whatever you would do after connection was canceled.
    } else {
            // Do whatever you would do after connection error or timeout
    }
}

答案 3 :(得分:0)

您可以使用类似这种结构的东西:

ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactory() {
  public Thread newThread(Runnable r) {
    Thread t = Executors.defaultThreadFactory().newThread(r);
    t.setDaemon(true);
    return t;
  }
});

Future<Socket> res = es.submit(() -> {
  try {
    return new Socket(addr, port);
  } catch (Exception ex) {
    logger.error("Error while connecting. " + ex.getMessage());
    return null;
  }
});

es.shutdown();

try {
  while (!res.isDone()) {
    Thread.sleep(5);
  }
} catch (InterruptedException iex) {
  logger.error("Connection interrupted.");
  return; 
}

Socket client = res.get();