Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Закрытие сокета 
:(
    Опции темы
LSD
Дата 29.8.2005, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Возникла у меня тут потребность посмотреть сколько времени занимает соединение с помощью сокета. Накидал тестик:
Сервер
Код
public class Server
{
  public static final String HOST = "localhost";
  public static final int PORT_NUMBER = 1234;

  private int port;
  private ServerSocket serverSocket;
  public AtomicBoolean listening = new AtomicBoolean(false);

  public Server(int port)
  {
    this.port = port;
  }

  public synchronized void startListening() throws IOException
  {
    listening.set(true);
    serverSocket = new ServerSocket(port);
    while(listening.get())
    {
      Socket s = serverSocket.accept();
      new SocketListener(s).start();
    }
    serverSocket.close();
    serverSocket = null;
  }

  public void stopListening()
  {
    listening.set(false);
  }

  public static void main(String[] args) throws IOException
  {
    Server server = new Server(PORT_NUMBER);
    server.startListening();
  }

  private static class SocketListener extends Thread
  {
    private Socket socket;

    public SocketListener(Socket socket)
    {
      this.socket = socket;
    }

    public void run()
    {
      try
      {
        InputStream in = socket.getInputStream();
        int i;
        while( (i = in.read()) != -1)
        {
          if(i != 69)
            System.err.println("Wrong data: " + i);
        }
        OutputStream out = socket.getOutputStream();
        out.write(33);
        socket.close();
      }
      catch(IOException ex)
      {
        ex.printStackTrace();
      }
    }
  }
}

Клиент
Код
public class Client
{
  private int port;
  private String host;

  public Client(String host, int port)
  {
    this.port = port;
    this.host = host;
  }

  public void send() throws IOException
  {
    Socket socket = new Socket(host, port);
    OutputStream out = socket.getOutputStream();
    out.write(69);
    socket.shutdownOutput();
    InputStream in = socket.getInputStream();
    int i;
    while( (i = in.read()) != -1)
    {
      if(i != 33)
        System.err.println("Wrong data: " + i);
    }
    socket.close();
  }

  public static void main(String[] args) throws IOException
  {
    Client client = new Client(Server.HOST, Server.PORT_NUMBER);
    long interval = System.currentTimeMillis();
    for(int i = 0; i < 10000; i++)
    {
      try
      {
        client.send();
      }
      catch(IOException ex)
      {
        System.err.println("Error: " + ex + ", at iteration " + i);
      }
    }
    interval = System.currentTimeMillis() - interval;
    System.out.println( (10000.0 / (interval / 1000.0)) + " conn/sec");
  }
}

А дальше происходит нечто интерестное, после некоторго количества итераций (около 4000) происходит ошибка: ava.net.BindException: Address already in use: connect и если посмотреть открытые порты то видно куча открытых подключений открытых lsass.exe:
netstat -anb
Код
Активные подключения

  Имя    Локальный адрес        Внешний адрес          Состояние
....
  TCP    127.0.0.1:2734         127.0.0.1:1234         TIME_WAIT
  TCP    127.0.0.1:2734         127.0.0.1:1234         TIME_WAIT
....
  [lsass.exe]
....

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


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
COVD
Дата 1.9.2005, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 11
Всего: 43



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

Это сообщение отредактировал(а) COVD - 1.9.2005, 21:32
PM MAIL   Вверх
Mayk
Дата 1.9.2005, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: нет
Всего: 134



Умора, у меня time_wait в линухе наоборот висит.
Сокет устанавливается в состояниее TIME_WAIT, для того чтобы на него не могли придти устаревшие пакеты, которые были посланы до того, как сокет закрылся. В частности об этом Стивенс подробно очень писал.

вот здесь, к примеру, обсуждается, что такое TIME_WAIT.

Хотя довольно непонятно, зачем это надо локальным соединениям.

Это сообщение отредактировал(а) Mayk - 1.9.2005, 22:06


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
vzf
Дата 9.9.2005, 09:57 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











понятно, что сокет не закрывают, ожидая, что кто-то ещё законнектится. Вопрос: есть ли какая-нибудь опция, чтобы время ожидание свести к минимуму (или вообще к 0) или это фантастика? Если кто подскажет, буду очень благодарен.
  Вверх
LSD
Дата 9.9.2005, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Цитата(vzf @ 9.9.2005, 10:57)
Вопрос: есть ли какая-нибудь опция, чтобы время ожидание свести к минимуму (или вообще к 0) или это фантастика?

Хороший вопрос, мне было бы тоже весьма интерестно это узнать как это сделать под виндами.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
COVD
Дата 9.9.2005, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 11
Всего: 43



Цитата
понятно, что сокет не закрывают, ожидая, что кто-то ещё законнектится


как написано выше, сокет перед удалением временно переводится в состояние ожидания, чтобы на него не пришли устаревшие пакеты. Не совсем ясно, но к новым коннектам это отношения вроде не имеет.

Вообще не понятно, почему такой интерес к этому времени ожидания. Ну, удалится этот сокет со временем. Максимальное количество сокетов в системе примерно 65000.

В приведенном выше тесте новые сокеты открываются без паузы, в цикле. Ситуация искусственная. Наверное, можно определить порог, максимальное число коннектов в единицу времени, при котором конкретный компьютер устойчиво открывает- закрывает новые соединения. Если этот порог не отвечает требованиям, то надо распараллеливать обработку.
PM MAIL   Вверх
Alone
Дата 9.9.2005, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: нет
Всего: 6



Может стоит поискать опцию похожую на SO_REUSEADDR?

цитата:
"В некоторых случаях система не позволяет программе привязаться к только что освобожденному порту, пока не дождется подтверждения приема всех данных, передававшихся через соответствующий сокет. В таком случае можно использовать этот ключ"



--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
vzf
Дата 9.9.2005, 17:29 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











[quote]Вообще не понятно, почему такой интерес к этому времени ожидания. Ну, удалится этот сокет со временем. Максимальное количество сокетов в системе примерно 65000.

У меня например клиент привязан к localhost на конкретный порт (так надо было), и после первого запуска бывает, что сокет на этот адрес находиться в TIME_WAIT, и снова клиент не запустить. Причем интересно, что если сервер не передает много данных клиенту, то такое случается редко, а если передает, то всегда. Точно, наверное, дело в пакетах.
  Вверх
AntonSaburov
Дата 9.9.2005, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 2
Всего: 118



Ну как сказать. А если тот же Томкэт надо перезапустить. А он при небольшом деплое стартует за секунды. И валиться при быстром перезапуске. Сам сталкивался.
PM MAIL WWW ICQ   Вверх
COVD
Дата 9.9.2005, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 11
Всего: 43



Цитата
У меня например клиент привязан к localhost на конкретный порт (так надо было), и после первого запуска бывает, что сокет на этот адрес находиться в TIME_WAIT, и снова клиент не запустить.


Сервер всегда слушает на конкретном порту X. При новом коннекте (accept) создается сокет, которому система назначает любой свободный порт Y, и клиент с ним работает в другом потоке. А сервер продолжает прослушивать порт X и готов принять новое соединение. Когда созданный сокет закрывается, то он еще некоторое время висит в системе на порту Y, пока не истечет TIME_WAIT.

Если же открытие сокета (accept) и его закрытие делать в одном потоке (как в приведенном выше тесте), то наверное из-за этого и возникают проблемы с TIME_WAIT, потому что сервер не может перейти к прослушиванию порта X, пока не закроется созданный сокет. Но имеет ли практическое применение такая однопоточная схема обработки?

Это сообщение отредактировал(а) COVD - 9.9.2005, 22:32
PM MAIL   Вверх
LSD
Дата 9.9.2005, 23:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Цитата(COVD @ 9.9.2005, 21:29)
Если же открытие сокета (accept) и его закрытие делать в одном потоке (как в приведенном выше тесте), то наверное из-за этого и возникают проблемы с TIME_WAIT, потому что сервер не может перейти к прослушиванию порта X, пока не закроется созданный сокет. Но имеет ли практическое применение такая однопоточная схема обработки?

Там используется много потоков, после accept запускается SocketListener, который и работает дальше с сокетом. Да это и не принципиально, даже если я в одном потоке открываю сокет и тут же его и закрываю, то это влияет только на то, как быстро я смогу выполнить accept для другого соединения. Потоки это внутренее дело приложения, не могут они влиять на системные вещи.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
COVD
Дата 10.9.2005, 00:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 11
Всего: 43



Цитата
Там используется много потоков, после accept запускается SocketListener, который и работает дальше с сокетом.

Да, я ошибся smile
PM MAIL   Вверх
vzf
Дата 10.9.2005, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 203
Регистрация: 10.9.2005

Репутация: нет
Всего: 5



Взял вчера да и открыл свою любимою книгу про TCP/IP протоколы. Там прочитал примерно следующее. Пара адресов используемых при соединении после его завершения не могут быть использованы системой в течении периода 2MSL(maximum segment lifetime). Это правило позволяет TCP-модулю в случае необходимости повторить последний сегмент ACK (если он потерялся в пути , то другая сторона после таймаута вышлет свой сегмент FIN). На стороне выполняющей активное закрытие будут в течении 2MSL ждать сегмент с FIN, остальные сегменты будут отбрасываться. Тем самым дается гарантия, что задержавшиеся сегменты от предыдущего воплощения соединения не будут спутаны с сегментами нового соединения.
В API сокетов можно указать опцию SO_REUSEADDR, которая позволит приложению назначить себе местный порт, когда он еще пребывает в состоянии TIME_WAIT. Однако протокол TCP не допускает, чтобы с участием такого порта было создано новое воплощение того соединения, которое находится в состоянии TIME_WAIT.
Но нарушение спецификации протокола TCP позволяет клиенту и серверу постоянно использовать заново те же номера портов для последовательных перевоплощений одного и того же соединения, НО ЛИШЬ В ТОМ СЛУЧАЕ, ЕСЛИ АКТИВНОЕ ЗАКРЫТИЕ ПРОИЗВОДИТ СЕРВЕР.

Вот так там бы ло написано, но все равно я так и не понял можно ли (и как) сделать это. smile
--------------------
Java - Write Once, Test EveryWhere!
PM MAIL   Вверх
LSD
Дата 10.9.2005, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 19
Всего: 538



Надо попробовать.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Mayk
Дата 10.9.2005, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: нет
Всего: 134



Цитата(LSD @ 9.9.2005, 15:06)
Цитата (vzf @ 9.9.2005, 10:57)
Вопрос: есть ли какая-нибудь опция, чтобы время ожидание свести к минимуму (или вообще к 0) или это фантастика?
Хороший вопрос, мне было бы тоже весьма интерестно это узнать как это сделать под виндами.


Статейка
Описывает как в винде изменить время на TIME_WAIT.

----8<----
Change the TIME_WAIT Timeout to Increase Connections (Windows NT/2000/XP)
This setting determines the length of time that a connection will stay in the TIME_WAIT state before being closed. The default is 240 seconds which on a busy server will limit the maximum connections to around 200/sec. Reducing this setting will increase the maximum connection limit.

Download this tweak with Tweak Manager! This tweak can be easily applied using WinGuides Tweak Manager.
Download a free trial now!

Open your registry and find or create the key below.

Create a new DWORD value, or modify the existing value, called "TcpTimedWaitDelay" and set it according to the value data below.

Exit your registry, you may need to restart or log out of Windows for the change to take effect.

Registry Editor Example
| Name Type Data |
| (Default) REG_SZ (value not set) |
| TcpTimedWaitDelay REG_DWORD 0x0000001e (30) |
-
| HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\P... |
-

Registry Settings
System Key: [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
Value Name: TcpTimedWaitDelay
Data Type: REG_DWORD (DWORD Value)
Value Data: 30-300 seconds (decimal)

Disclaimer: Modifying the registry can cause serious problems that may require you to reinstall your operating system. We cannot guarantee that problems resulting from modifications to the registry can be solved. Use the information provided at your own risk.

Last Modified: June 18
---->8----

Цитата(vzf @ 10.9.2005, 19:52)
Вот так там бы ло написано, но все равно я так и не понял можно ли (и как) сделать это.

ну REUSE можно попробовать поставить через Socket.setReuseAddress() и проверить.



--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Работа с сетью | Следующая тема »


 




[ Время генерации скрипта: 0.0592 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.