Jump to content

    
Ruslan1

Можно ли уменьшить количество TCP соединений со статусом "TIME_WAIT" на удаленном сервере?

Recommended Posts

Начитался в интернете, что TCP соединение на сервере после закрытия все еще занято в течении 2*MSL и имеет статус "TIME_WAIT".

А может ли клиент как-нибудь сказать серверу что оно "точно-точно закрыто, гейтсом клянусь!", так чтоб сервер перестал считать соединение занятым раньше, чем после 2*MSL ?

 

Нашел вот такой документ прошлого века, где предлагается обход: https://tools.ietf.org/html/draft-faber-time-wait-avoidance-00

там описан дополнительный пересыл RTS, и авторы документа таким образом патчили определенные системы.

Quote

rom CLOSE_WAIT based on whether the application issues a close or a
   close_swap.

   The current passive close path is:


      server                            client
      -----------------------------------------------------------
      ESTABLISHED                       ESTABLISHED
      (get application close)
      goto FIN_WAIT_1
      send FIN           ---FIN--->
                                        goto CLOSE_WAIT
                        <---ACK---      send ACK
      goto FIN_WAIT_2
                                        (get application close)
                                        goto LAST_ACK

                        <---FIN---      send FIN
      goto TIME_WAIT
      send ACK           ---ACK--->
                                        goto CLOSED


   This solution adds this branch from CLOSE_WAIT on the client side:


      server                            client
      -----------------------------------------------------------
      ESTABLISHED                       ESTABLISHED
      (get application close)
      goto FIN_WAIT_1
      send FIN           ---FIN--->
                                        goto CLOSE_WAIT
                        <---ACK---      send ACK
      goto FIN_WAIT_2
                                        (get application close_swap)
                                        goto LAST_ACK_SWAP
                        <---FIN---      send FIN
      goto TIME_WAIT
      send ACK           ---ACK--->
                                        goto TIME_WAIT
                        <---RST---      send RST
      goto CLOSED

   Strictly speaking, the transition of the client to TIME_WAIT is
   extraneous, because any host sending an RST is obligated not to allow
   a connection between the same pair of addresses and ports for a time
   of at least 2 MSL.

Но да, нужно дополнительно на клиенте не использовать этот порт следующие 2*MSL время, и вообще это не стандарт. И вообще статью написали 22 года назад.

А стандартно ничего не придумали с тех пор?

Откуда вопрос возник: есть встроенный FTP сервер, где количество возможных соединений небольшое, и там в ограничение очень легко превысить, если много мелких файлов передавать: насколько я понял, каждый порт остается висеть эти 2*MSL и считается занятым. И очень хотелось бы помочь решить эту проблему со стороны клиента (если возможно), может действительно у меня в lwIP чего-то покрутить можно, и серверу станет легче.

Share this post


Link to post
Share on other sites
56 минут назад, Ruslan1 сказал:

А может ли клиент как-нибудь сказать серверу что оно "точно-точно закрыто, гейтсом клянусь!", так чтоб сервер перестал считать соединение занятым раньше, чем после 2*MSL ?

Причём тут "клиент" и его состояние? Это время никак не зависит от состояния клиента.

Share this post


Link to post
Share on other sites
1 час назад, Ruslan1 сказал:

А стандартно ничего не придумали с тех пор?

Откуда вопрос возник: есть встроенный FTP сервер, где количество возможных соединений небольшое, и там в ограничение очень легко превысить

Стандартно - увеличить число доступных соединений в TCP-стеке. И мудрить ничего не надо :wink:

Share this post


Link to post
Share on other sites
1 час назад, Ruslan1 сказал:

Откуда вопрос возник: есть встроенный FTP сервер, где количество возможных соединений небольшое, и там в ограничение очень легко превысить, если много мелких файлов передавать: насколько я понял, каждый порт остается висеть эти 2*MSL и считается занятым. И очень хотелось бы помочь решить эту проблему со стороны клиента (если возможно), может действительно у меня в lwIP чего-то покрутить можно, и серверу станет легче.

Со стороны клиента можно увеличить таймауты между передаваемыми файлами - передачу ведь инициирует клиент, а  со стороны сервера только собрать ftp-сервер с нужными задержками.

А так то в чём проблема - сервер скажет busy, клиент подождёт и еще раз попытается передать файл.

Share this post


Link to post
Share on other sites
40 minutes ago, jcxz said:

Причём тут "клиент" и его состояние? Это время никак не зависит от состояния клиента.

перефразирую, если фраза чересчиу витиевата и сложна для понимания: Может ли клиент как-то сообщить серверу, что он не собирается ничего больше прередавать, и заставить сервер забыть об этом соединении быстрее, чем 2*MSL ?

25 minutes ago, jcxz said:

Стандартно - увеличить число доступных соединений в TCP-стеке. И мудрить ничего не надо :wink:

Я тоже не люблю встроенные FTP, но вот попался у одной конторы synology с запасом 512 соединений. И есть у меня подозрение, что эта цифра "512" относится ко всему устройству, а не конкретно под FTP выделено.

Share this post


Link to post
Share on other sites
13 минут назад, Ruslan1 сказал:

Может ли клиент как-то сообщить серверу, что он не собирается ничего больше прередавать, и заставить сервер забыть об этом соединении быстрее, чем 2*MSL ?

Ещё раз - зачем? Если вопрос слишком сложен для понимания, :wink: перефразирую: Чем это поможет?

Share this post


Link to post
Share on other sites
10 minutes ago, HardEgor said:

Со стороны клиента можно увеличить таймауты между передаваемыми файлами - передачу ведь инициирует клиент, а  со стороны сервера только собрать ftp-сервер с нужными задержками.

Ситуация смешная- все началось после того, как новая прошивка стала доставлять данные раз в 10 быстрее. Что при наличии кучки мелких файлов понятно к чему ведет.

Ну что ж, как ускорил- так и замедлить смогу, вероятно лучше всего ограничить количество TCP соединений в единицу времени. Если превышено- рвать соединение и впадать в коммуникационную спячку на сколько-нибудь MSL.

 

10 minutes ago, HardEgor said:

А так то в чём проблема - сервер скажет busy, клиент подождёт и еще раз попытается передать файл.

У меня кучка приборов рандомно данные кидают. И в результате кто-то часто достукивается, а кто-то раз в час получает "счастливый билетик". Ну, раз нельза вылечить, попробую просто упорядочить это безобразие.

1 minute ago, jcxz said:

Ещё раз - зачем? Чем это поможет?

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

Share this post


Link to post
Share on other sites
8 минут назад, Ruslan1 сказал:

У меня кучка приборов рандомно данные кидают. И в результате кто-то часто достукивается, а кто-то раз в час получает "счастливый билетик". Ну, раз нельза вылечить, попробую просто упорядочить это безобразие.

Ну так на стороне сервера можно же как-то наверное разравнивать приоритеты "достукивания". Если есть доступ к его коду. Можно придумать алгоритм. Например: после успешного соединения, понижать приоритет для данного клиента до минимума. А все свободные сокеты разбить на группы по приоритету: одна группа - позволяет входящие соединения от клиентов с любым уровнем приоритета, а другая группа - только с уровнем не ниже некоторого значения.

8 минут назад, Ruslan1 сказал:

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

Тогда такой сервер нарушит правила работы TCP. :unknw:

Вы видимо плохо читали описание TCP и для чего нужно TIME_WAIT.

Share this post


Link to post
Share on other sites
1 hour ago, Ruslan1 said:

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

Ну так посыл последнего RST и происходит со стороны клиента. Добавьте там генерацию такого сегмента в состоянии получения ACK на FIN, и все будет хорошо.

Share this post


Link to post
Share on other sites
7 minutes ago, jcxz said:

Ну так на стороне сервера можно же как-то наверное разравнивать приоритеты "достукивания". Если есть доступ к его коду. Можно придумать алгоритм. Например: после успешного соединения, понижать приоритет для данного клиента до минимума. А все свободные сокеты разбить на группы по приоритету: одна группа - позволяет входящие соединения от клиентов с любым уровнем приоритета, а другая группа - только с уровнем не ниже некоторого значения.

Согласен. но уже несколько раз видел как, люди бодаются с разными zyxel, synology и прочими, где как бы уже есть FTP.

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

4 minutes ago, Rst7 said:

Ну так посыл последнего RST и происходит со стороны клиента. Добавьте там генерацию такого сегмента в состоянии получения ACK на FIN, и все будет хорошо.

То есть этот RST стандартно кем-то ждется? Ага, попробую понять. вроде и в инете что-то гуглится на тему RST. Попробую.

Смутило то, что все нагугленные картинки по стейт-машине TCP на сервере заканчиваются состоянием WAIT_TIME.

Share this post


Link to post
Share on other sites
22 минуты назад, Ruslan1 сказал:

Ну что ж, как ускорил- так и замедлить смогу, вероятно лучше всего ограничить количество TCP соединений в единицу времени. Если превышено- рвать соединение и впадать в коммуникационную спячку на сколько-нибудь MSL.

Термин CSMA/CD поможет. Множество желающих на ограниченный ресурс - простые случайные задержки между файлами помогут, особенно если готовность возникает почти синхронно.

 

10 минут назад, Ruslan1 сказал:

Смутило то, что все нагугленные картинки по стейт-машине TCP на сервере заканчиваются состоянием WAIT_TIME.

Есть в TCP/IP разные подводные камни и разные сервера их решают по разному....

Share this post


Link to post
Share on other sites
28 minutes ago, Rst7 said:

Ну так посыл последнего RST и происходит со стороны клиента. Добавьте там генерацию такого сегмента в состоянии получения ACK на FIN, и все будет хорошо.

вот тут обсуждается: http://lwip.100.n7.nabble.com/How-to-send-RST-td8880.html

Quote

err_t
tcp_close(struct tcp_pcb *pcb)
{
 ....
  case ESTABLISHED:
    if( rstClose & 0x1) // rstClose is a control flag.
    {
        err = tcp_send_ctrl(pcb, TCP_FIN);
        if (err == ERR_OK) {
          snmp_inc_tcpestabresets();
          pcb->state = FIN_WAIT_1;
        }
    }
    else
    {
        tcp_abort(pcb);
        err = ERR_OK;
        pcb = NULL;
    }
    break;
...
}

но там же и комментарий

Quote

It looks like you made changes to cause the stack to send RST instead of FIN when you close the socket (at least in some situations - there's not enough context to indicate when rstClose would be set).
That might be a reasonable choice in your particular environment but it's not a very good plan in the general case.  It risks stranding resources in the peer in the event that the RST packet gets dropped somewhere in the path between the two hosts.
By default, TCP connections don't time out. So, if your RST packet is lost, the peer will just never hear from you again but will think that the connection is still alive.  Even with TCP keepalives enabled (and they are not enabled by default in most systems), the default connection idle timeout is usually two hours. This is probably why the ability to generate RST packets is not typically extended to applications: it's not meant for ordinary session teardown; it's intended to notify the peer of an exceptional condition.
Again, this may be fine for your environment, but someone else looking at your suggestion should be aware of the consequences.

В-общем, как-то и мне не хочется одно другим подменять. А еще он в WireShark красным показывается, что как бы намекает на необычность действия.

Share this post


Link to post
Share on other sites

Код lwIP открыт.  Его можно поправить в нужную вам сторону. Код не сложный.  Я переделывал под свои нужды для PIC32. Знаю одного кадра , который для STM много че там переделал в этом стеке.

Share this post


Link to post
Share on other sites
34 minutes ago, Ruslan1 said:

В-общем, как-то и мне не хочется одно другим подменять.

Не надо заменять FIN на RST. Надо послать дополнительный сегмент (RST) при приходе валидного ACK в состоянии CLOSING и LAST-ACK.

37 minutes ago, Ruslan1 said:

А еще он в WireShark красным показывается, что как бы намекает на необычность действия.

Ну WireShark много чего красным красит. Это ж не повод для беспокойства в конкретно данном случае.

Share this post


Link to post
Share on other sites

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

Сказано же:

"Другое назначение ожидания 2MSL заключается в том, что пока TCP соединение находится в ожидании 2MSL, пара сокетов, выделенная для этого соединения (IP адрес клиента, номер порта клиента, IP адрес сервера и номер порта сервера), не может быть повторно использована. Это соединение может быть использовано повторно только когда истечет время ожидания 2MSL."

Вполне обоснованное требование. Потому сервер и должен выдерживать TIME_WAIT.

"Это делается для того, чтобы опоздавшие пакеты не были восприняты как часть нового соединения".

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.