Почему .Net Socket.Disconnect занимает две минуты? - PullRequest
7 голосов
/ 03 декабря 2010

Я использую класс сокета .Net и использую следующий код:

socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(true);

Это блокирует ровно две минуты. Я указал true, потому что собираюсь немедленно повторно использовать сокет и восстановить соединение. Есть ли у меня вызов выключения или нет, он блокируется на две минуты. Единственное, что я могу сделать, это передать false, чтобы отключиться. Но я хочу повторно использовать сокет.

Есть идеи?

UPDATE:

Я прочитал коды. Я установил опцию DontLinger. Это не помогает.

ОБНОВЛЕНИЕ 2:

Я добавил трассировку сети согласно запросу:

Trace 1: использование опции DontLinger

System.Net.Sockets Verbose: 0 : [4668] Socket#5009246::Socket(InterNetwork#2)
System.Net.Sockets Verbose: 0 : [4668] Exiting Socket#5009246::Socket() 
System.Net.Sockets Verbose: 0 : [4668] Socket#5009246::Connect(eee:nnnn#-2063562120)
System.Net.Sockets Information: 0 : [4668] Socket#5009246 - Created connection from aaa.bbb.ccc.ddd.eee:nnnnn to www.xxx.yyy.zzz.:mmmm.
System.Net.Sockets Verbose: 0 : [4668] Exiting Socket#5009246::Connect() 
System.Net.Sockets Verbose: 0 : [4668] Socket#5009246::Disconnect()
System.Net.Sockets Verbose: 0 : [4668] Exiting Socket#5009246::Disconnect() 

Трассировка 2: Использование выключения (SocketShutdown.Both);

System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Socket(InterNetwork#2)
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Socket() 
System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Connect(ddd:eeeee#-2063562120)
System.Net.Sockets Information: 0 : [0300] Socket#5009246 - Created connection from aaa.bbb.ccc.ddd:eeee to www.xxx.yyyy.zzzz:nnnnn.
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Connect() 
System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Shutdown(Both#2)
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Shutdown() 
System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Disconnect()
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Disconnect() 

Ответы [ 5 ]

3 голосов
/ 31 июля 2013

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

Вот как это работает: Выключение (SocketShutdown.Send) (или оба) производит SENDING нулевого байта на другую сторону. И затем, если вы вызовете Disconnect, он заблокируется, пока другая сторона не примет этот пакет нулевого байта. Вот почему сокет всегда получает нулевой байт во время принятия, во время постепенного отключения от сокета. Опция Linger и другие настройки не влияют на эту 2-минутную задержку. Вы можете проверить состояние соединения с TCPView. Поэтому правильный способ - убедиться, что другая сторона либо находится в режиме приема, либо физически отключена, либо фактически уничтожила сокет - например, приложение завершило работу (в этом случае вы получите немедленное исключение без задержки 2 минуты).

http://vadmyst.blogspot.ru/2008/04/proper-way-to-close-tcp-socket.html

1 голос
/ 03 декабря 2010

Это может быть то, что вы ищете.

Если вам нужно вызвать Disconnect без предварительного вызова Shutdown, вы можете установить для параметра DontLinger Socket значение false и указать ненулевой интервал времени ожидания, равныйубедитесь, что данные, поставленные в очередь для исходящей передачи, отправлены.Затем отключите блоки, пока данные не будут отправлены или пока не истечет указанное время ожидания.Если для DontLinger задано значение false и указан нулевой интервал времени ожидания, Close освобождает соединение и автоматически отбрасывает исходящие данные в очереди.

Из документов .

0 голосов
/ 21 февраля 2019

Это занимает 2 минуты, потому что сервер, вероятно, не закрыл сокет, когда получил 0 байтов от вызова завершения работы клиента.

Итак, отключение вызова клиента.Сервер получает 0 байтов.Вызов клиента Disconnect: disconnect будет ожидать закрытия сокета со стороны сервера.Если сервер не закроет сокет, отключение клиента займет 2 минуты (время ожидания).Если сервер закроет сокет, отключение будет почти мгновенным.

0 голосов
/ 21 января 2011

Оказывается, есть некоторая запись в реестре, которая контролирует, сколько времени занимает отключение.Это как-то связано с API WinSock2.

0 голосов
/ 03 декабря 2010

Это может быть вариант Linger.Для получения дополнительной информации см. Здесь: Изящное завершение работы, параметры задержки и закрытие сокета

в .NET, вы можете изменить его с помощью метода Socket.SetSocketOption.* EDIT : если это не опция Linger, попробуйте включить полные трассировки сокетов, вот пример .config:

<configuration>
  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.Net.Sockets">
        <listeners>
          <add name="SocketsTrace"/>
        </listeners>
      </source>
    </sources>

    <sharedListeners>
      <add name="SocketsTrace" type="System.Diagnostics.TextWriterTraceListener" initializeData="SocketsTrace.log" />
    </sharedListeners>

    <switches>
      <add name="System.Net.Sockets" value="Verbose" />
    </switches>
 </configuration>

EDIT : или вы можете нажатьто, что называется TIME_WAIT, описано здесь: Пожалуйста, объясните состояние TIME_WAIT , которое составляет 120 мс.Как правило, лучше использовать Close () с SocketOptionName.ReuseAddress, чем использовать Disconnect (true).См. Также комментарии здесь (в разделе комментариев).

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