2016-11-13 3 views
2

Я пытаюсь создать многопоточный сервер, к которому могут подключаться несколько клиентов. Однако я не уверен, как правильно освободить свои ресурсы, если возникнет такая необходимость.Java: правильно закрывающие сокеты для многопоточных серверов

Мой сервер запускает входной поток (ожидание пользовательских входов) и обрабатывающий поток (обрабатывает соединения и пользователей). Я открываю ServerSocket в классе сервера и передаю его в поток обработки. Это выглядит следующим образом:

public class ClientConnector implements Runnable { 

private ServerSocket serverSocket; 

public ClientConnector(ServerSocket serverSocket) { 
    this.serverSocket = serverSocket; 
} 

@Override 
public void run() { 
    ExecutorService tcpExecutor = Executors.newCachedThreadPool(); 

    while (!serverSocket.isClosed()) { 
     Socket clientSocket = null; 

     try { 
      clientSocket = serverSocket.accept(); 
     } catch (IOException e) { 
      System.err.println("could not accept connection"); 
     } 

     if (clientSocket != null) { 
      tcpExecutor.execute(new ClientHandler(clientSocket); 
     }   
    } 
} 
} 

Если я хочу, чтобы выйти, я просто запустить этот метод в моем классе сервера, чтобы закрыть ServerSocket:

public void exit() { 
    try { 
     serverSocket.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

которая должна привести к следующему serverSocket.accept() вызов вызывать исключение, и цикл останавливается после закрытия сокета.

Мой вопрос: закрытие ServerSocket неявно закрывает ClientSockets, которые были созданы с его помощью? Или я должен обязательно закрыть каждый открытый клиентский ключ вручную? Если да, есть ли простой способ сделать это, а не сохранять каждое соединение, сделанное на сервере где-нибудь?

+0

Проблема заключается в том, что любые сокеты, которые открываются в то время, когда мы закрываем сокет сервера, открыты, потому что они заблокированы, ожидая ввода от клиента. И их странный вид блокировки, который нельзя даже прервать. Даже трюк отправки пустого пакета для разблокировки сокета не работает, потому что они ждут уже установленных соединений с третьими лицами, вы не можете вставлять пустой пакет в эти соединения. Итак, вы нашли решение? –

ответ

0

ли закрытие ServerSocket неявно закрывает ClientSockets, которые были созданы с его помощью?

Нет, это не влияет на них.

Или я должен обязательно закрыть каждый открытый клиентский ключ вручную?

Да, и вы должны делать это в любом случае в каждом потоке обработчика.

Если да, то есть ли простой способ сделать это, а не сохранять каждое соединение, сделанное на сервере где-нибудь?

Просто наложите таймаут чтения и закройте каждый сокет, который истекает. Это нормальная часть любого сервера. Вам не нужно собирать сокеты или предпринимать какие-либо специальные меры для их остановки.

0

Нет, это не так. Он просто закрывает ServerSocket, что означает, что новые соединения не могут быть выполнены. Существующие открытые сокеты будут продолжать работать.

Нет никакого «простого» способа закрыть все открытые сокеты, потому что на самом деле его не сложно начать (или если вы обнаружите, что это сложная часть в сетевом программировании, происходит что-то очень странное).

0

Позвольте клиенту обработать поток, закрывает клиентский сокет в конце обработки.

Смежные вопросы