Почему сокеты не умирают, когда умирает сервер? Почему сокет умирает, когда сервер жив? - PullRequest
1 голос
/ 17 марта 2010

Я стараюсь немного поиграть с сокетами. Для этого я написал очень простые «клиентские» и «серверные» приложения.

Клиент:

import java.net.*;

public class client {
    public static void main(String[] args) throws Exception {
    InetAddress localhost = InetAddress.getLocalHost();
    System.out.println("before");

    Socket clientSideSocket = null;
    try {
        clientSideSocket = new Socket(localhost,12345,localhost,54321);
    } catch (ConnectException e) {
        System.out.println("Connection Refused");
    }
    System.out.println("after");

    if (clientSideSocket != null) {
        clientSideSocket.close();
    }
    }
}

Сервер:

import java.net.*;

public class server {
    public static void main(String[] args) throws Exception {
    ServerSocket listener = new ServerSocket(12345);

    while (true) {
        Socket serverSideSocket = listener.accept();
        System.out.println("A client-request is accepted.");
    }

    }
}

И я обнаружил поведение, которое не могу объяснить:

  1. Я запускаю сервер, затем запускаю клиент. Соединение успешно установлено (клиент перестает работать, а сервер работает). Затем я закрываю сервер и запускаю его снова через секунду. После этого я запускаю клиент, и он пишет «Отказ в соединении». Мне кажется, что сервер «запоминает» старое соединение и не хочет дважды открывать второе соединение. Но я не понимаю, как это возможно. Потому что я убил предыдущий сервер и запустил новый!

  2. Я не запускаю сервер сразу после того, как предыдущий был убит (я жду около 20 секунд). В этом случае сервер «забывает» сокет от предыдущего сервера и принимает запрос от клиента.

  3. Я запускаю сервер, а затем запускаю клиент. Соединение установлено (сервер пишет: «Клиент-запрос принят»). Затем я подожду минуту и ​​снова запустите клиент. И сервер (который работал все время) снова принимает запрос! Зачем? Сервер не должен принимать запрос от одного и того же IP-адреса клиента и порта клиента, но он принимает!

Ответы [ 3 ]

4 голосов
/ 17 марта 2010
  1. Когда вы закрываете сервер, ОС некоторое время будет поддерживать работу сокета, чтобы он мог сообщить клиенту, что соединение было закрыто. Это включает таймауты и повторные передачи, которые могут занять некоторое время. Вы можете найти некоторую информацию здесь и здесь . Если вы хотите, чтобы ваш сервер мог немедленно перепривязать тот же сокет, вызовите setReuseAddress (true) на нем, хотя это могут быть клиентские сокеты, которые находятся в состоянии TIME_WAIT.

  2. Сокет больше не находится в состоянии TIME_WAIT и может быть снова использован любой программой.

  3. Ваш клиентский код просто подключается, закрывает сокет и затем завершает работу. Что касается стека tcp сервер / ОС, это разные соединения - хорошо использовать исходный порт, если любое предыдущее соединение было разорвано. (Обратите внимание, что ОС может не разорвать всю служебную работу соединения сразу после того, как вы вызовете .close () или ваша программа завершается, есть некоторая задержка, поэтому можно быть уверенным, что все пакеты были отправлены / получены)

0 голосов
/ 17 марта 2010

По Вопросу № 3: Многие клиенты могут подключаться к серверу, подключенному к одному порту. Apache работает через порт 80, но это не означает, что только один человек может просматривать ваш сайт одновременно. Также вы закрываете свой клиентский сокет перед тем, как открывать новый.

0 голосов
/ 17 марта 2010

Вероятно, операционная система еще не закрыла сокеты, попробуйте команду netstat (должна работать в Windows или Unix / Linux). Если вы запускаете его сразу после закрытия клиента или сервера, вы все равно должны использовать сокет в «TIME_WAIT», «CLOSE_WAIT» или в чем-то подобном. Вы не сможете повторно использовать эти порты, пока они не будут полностью закрыты.

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