Java медленный socket.connect () - PullRequest
       1

Java медленный socket.connect ()

5 голосов
/ 25 января 2011

Ниже приведен исходный код клиента и сервера. Клиент просто подключается (одновременно) к серверу и немедленно закрывает соединение. Когда все потоки завершены, он ждет 2 минуты и снова подключается. Меня смущает тот факт, что иногда простому соединению требуется около 3 секунд! Большую часть времени для соединения требуется всего около 0-32мс.

Вот типичный вывод от клиента:

...
Connect 23 [ms]: 16
Connect 22 [ms]: 32
Connect 21 [ms]: 32
Connect 15 [ms]: 32
Connect 14 [ms]: 16
Connect 13 [ms]: 16
Connect 11 [ms]: 32
Connect 25 [ms]: 3016

Похоже, это происходит только в том случае, если клиент и сервер находятся на разных хостах. Windows и Linux сопоставимое поведение Java 1.6.23

для запуска сервера необходимо 2 параметра: [порт] [размер пула потоков]

для запуска клиента необходимо 3 параметра: [хост] [порт] [размер пула потоков]

для примера я использовал размер пула потоков 150 для сервера и размер пула потоков 25 для клиента.

Кто-нибудь может объяснить это поведение?

----- сервер -----

package de.test.server;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServerApp {

   public static void main(String[] args) throws IOException {
      System.out.println("server running...");

      final int port = Integer.parseInt(args[0]);
      final int threads = Integer.parseInt(args[1]);
      final ExecutorService executorService = Executors
            .newFixedThreadPool(threads);
      ServerSocket serverSocket = new ServerSocket(port);
      while (true) {
         final Socket clientSocket = serverSocket.accept();

         executorService.execute(new Runnable() {
            @Override
            public void run() {
               try {
                  InputStream is = clientSocket.getInputStream();
                  int read = is.read();
                  if (read != -1) {
                     System.out.println("should not happen");
                  }
               } catch (IOException e) {
                  throw new RuntimeException(e);
               } finally {
                  close(clientSocket);
                  System.out.println("connection closed");
               }
            }

            private void close(final Socket connection) {
               try {
                  connection.close();
               } catch (IOException e1) {
                  throw new RuntimeException(e1);
               }
            };
         });
      }
   }
}

----- клиент -----

package de.test.client;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

public class ConnectApp {

   public static void main(String[] args) throws InterruptedException {
      final String host = args[0];
      final int port = Integer.parseInt(args[1]);
      final int THREAD_COUNT = Integer.parseInt(args[2]);

      final ExecutorService executorService = Executors
            .newFixedThreadPool(THREAD_COUNT);
      final AtomicLong threadCounter = new AtomicLong(0);
      while (true) {
         final CountDownLatch doneSignal = new CountDownLatch(THREAD_COUNT);
         for (int i = 0; i < THREAD_COUNT; i++) {
            executorService.execute(new Runnable() {
               @Override
               public void run() {
                  Socket socket = null;
                  try {
                     long start = System.currentTimeMillis();
                     socket = new Socket();

                     socket.setTcpNoDelay(true);
                     socket.connect(new InetSocketAddress(host, port));
                     System.out.println(socket.getTcpNoDelay());
                     long stop = System.currentTimeMillis();
                     System.out.println("Connect "
                           + threadCounter.incrementAndGet() + " [ms]: "
                           + (stop - start));
                  } catch (UnknownHostException e) {
                     throw new RuntimeException(e);
                  } catch (IOException e) {
                     throw new RuntimeException(e);
                  } finally {
                     close(socket);
                     doneSignal.countDown();
                  }

               }

               private void close(Socket socket) {
                  try {
                     if (socket != null)
                        socket.close();
                  } catch (IOException e1) {
                     throw new RuntimeException(e1);
                  }
               }
            });
         }
         doneSignal.await();
         System.out.println("Waiting 2 minutes...");
         Thread.sleep(1000 * 60 * 2);
      }
   }
}

1 Ответ

2 голосов
/ 26 января 2011

Все ваши сокеты пытаются подключиться одновременно.Поскольку все они пытаются подключиться к одному и тому же однопоточному серверу, один из них будет принят, 50 (по умолчанию) будут находиться в резерве, и сброс может не установить соединение или ждать слишком долго.

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

Кстати: вы звоните только threadCounter.incrementAndGet(), так почему же он идет вверх и вниз?Вы можете просто использовать

for (int i = 0; i < THREAD_COUNT; i++) {
    final int threadCount = i;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...