Программирование на сокете: при отключении клиента сервер зависает - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь создать образец TCP Forwarder. Вот краткая функциональность:

  1. Сервер пересылки будет прослушивать данный порт.
  2. Содержит карту клиентов на серверы
  3. Клиенты будут подключаться к серверу пересылки, а сервер пересылки будет искать карту и создавать двухстороннее соединение переадресации.
  4. Для этого создается два потока для каждого клиента.
  5. Поток 1: чтение с клиента и запись на целевой сервер
  6. Поток 2: чтение с целевого сервера и запись клиенту.

Все это написано на C. Серверы Client и Target могут быть написаны на любом языке, прямо сейчас на Java.

Когда я запускаю клиент в первый раз, он работает как положено. Однако, если я убью клиента и перезапущу его, сервер никогда не получит новое соединение.

Вот мой код сервера, который, я подозреваю, является ошибкой.

Socket clientSocket = serverSocket.accept();
InputStream inputStream = clientSocket.getInputStream();
OutputStream outputStream = clientSocket.getOutputStream();

while (true) {
    byte[] bArray = new byte[2048];
    try {
        System.out.println(String.format("SERVER:%s: Attempting to read", this.name));
        inputStream.read(bArray);
        System.out.println(String.format("SERVER:%s: Received %s", this.name, new String(bArray)));
        byte[] bytes = (name + ":" + counter).getBytes();
        counter++;
        outputStream.write(bytes);
        System.out.println(String.format("SERVER:%s: Sent %s", this.name, new String(bytes)));
    } catch (IOException e) {
        System.out.println(String.format("SERVER:%s: Client Disconnected ", this.name));
        clientSocket = serverSocket.accept();
        inputStream = clientSocket.getInputStream();
    }
}

В программе на C я обнаруживаю отключение и закрываю розетку, как показано ниже:

LOGINFO("Reading from Client Socket.");
iResult = read(readSocket, buff, recvbuflen);
if (iResult <= 0) {
    LOGERROR("Receiving failed");
    close(readSocket);          
    break;
}

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Вы должны использовать

   shutdown(socket_fd, SHUT_WR);

вместо close(socket_fd) для правильного закрытия сокета.

Если вы используете SHUT_WR, пакет FIN будет отправлен другой стороне, чтобы сообщить им, что у нас нет больше данных для отправки.

0 голосов
/ 09 мая 2018

Попробуйте изменить логику вашего сервера, используя параллелизм для управления каждым запросом. Таким образом, сервер сможет обрабатывать каждого клиента отдельно в потоке. Чтение и запись данных должны выполняться в соответствующей теме. Парадигма потоков пула часто используется, чтобы избежать издержек потока [1] .

Например:

ExecutorService threadPool = Executors.newFixedThreadPool(n);
ServerSocket serverSocket = null;

//...

while(!isStopped()){
   Socket clientSocket = null;
   try {
       clientSocket = this.serverSocket.accept();
       threadPool.execute(new WorkerRunnable(clientSocket));
       // Process data in the WorkerRunnable class
   } catch (IOException e) {
       if(isStopped()) {
           System.err.println("Server Stopped.") ;
           break;
       }
       throw new RuntimeException("Error accepting client connection", e);
   } 
}

Хорошо разработанный пример можно найти здесь: http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...