HttpWebRequest держит сокет в ожидании времени - PullRequest
1 голос
/ 31 мая 2011

Мне трудно разобраться, пока HttpWebRequest в .NET 4.0 создает сокет-соединение для каждого запроса, но впоследствии не может закрыть сокет.Когда я выполняю, например, 50 запросов HttpWebRequest, я вижу 50 соединений сокетов TCP в состоянии WAIT в netstat.

Я уже уменьшил код до минимума:

Dim webReq As HttpWebRequest
    Dim webRes As HttpWebResponse
    Dim webStream As IO.StreamReader
    Dim _answer As String

    webReq = System.Net.HttpWebRequest.Create(TextBox1.Text)
    webReq.Timeout = 10000
    webReq.Method = WebRequestMethods.Http.Get
    webRes = webReq.GetResponse

    webStream = New IO.StreamReader(webRes.GetResponseStream(), System.Text.Encoding.ASCII())
    _answer = webStream.ReadToEnd
    RichTextBox1.Text = _answer

    webRes.Close()
    webRes = Nothing
    webReq = Nothing

Любая идея, подсказка приветствуется!

Заранее спасибо

Крис

Ответы [ 2 ]

2 голосов
/ 14 июня 2011

После того, как я получил более глубокое понимание этой темы, я могу дать ответ сам себе.

Всякий раз, когда вы открываете и закрываете сокет, он переходит в состояние «ВРЕМЯ ОЖИДАНИЯ», прежде чем полностью закрыться. Это состояние должно препятствовать тому, чтобы следующее tcp-соединение получало задержанные tcp-пакеты позже. Я имел дело с приложением, которое отправляет несколько тысяч CGI-запросов на сервер. Проблема заключалась в том, что сервер использовал HTTP / 1.0, что означает, что каждый запрос открывает новый сокет и закрывает его сразу после обмена данными. Через некоторое время тысячи соединений tcp показываются в netstat в состоянии «ВРЕМЯ ОЖИДАНИЯ». Разъемы, или, если быть более точными, порты стали исчерпаны. Windows не предоставляла приложению новые сокеты для новых запросов CGI. Через некоторое время все сокеты TIME-WAIT были закрыты, и приложение могло продолжить связь. Эта проблема возникла из-за природы сервера HTTP / 1.0.

Существует два «исправления» этой проблемы с точки зрения Windows. Изменяя REGISTRY, вы можете позволить Windows управлять более чем 5000 соединений по умолчанию (я прочитал хороший верхний предел, который может быть 20.000). Другой вариант - уменьшить время ожидания. Это также может быть сделано путем настройки реестра. Оба варианта не были реальным решением нашей огромной проблемы с истощением сокетов.

В конечном решении мы использовали опцию сокета TCP под названием «SO-LINGER». Установка этой опции при создании порта позволяет пропустить состояние TIME-WAIT сокета TCP. Пожалуйста, имейте в виду, что это состояние существует по причине! Пропуск этого был одним из последних вариантов и соответствует нашим потребностям, потому что мы передаем пару байтов через сокет. Перед использованием этой опции рассмотрите возможные воздействия.

Проект разработан в VB .NET 4.0. Код, который я использовал для создания сокета, размещен ниже:

Private _plcAddress As String
Private _plcSocket As Socket
Private _endPoint As IPEndPoint

...

   Dim myOpts As New LingerOption(True, 0)
   Dim ipAddress As IPAddress = ipAddress.Parse(plcAddress)

    _plcAddress = plcAddress
    _plcSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP)
    _plcSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, myOpts)
    _endPoint = New IPEndPoint(IPAddress, 80)
...
0 голосов
/ 31 мая 2011

Вы имеете в виду «TIME_WAIT»?Если это так, сделайте 50 запросов, выпейте кофе, вернитесь в свою коробку, перепроверьте с помощью netstat.

Закрытие сокета TCP выполняет рукопожатие завершения и ставит объект сокета в очередь для освобождения.Сокет фактически не освобождается в течение нескольких минут по схеме TCP - некоторые пакеты могут все еще находиться в пути по медленным маршрутам даже после успешного завершения соединения, и поэтому сокет нельзя перераспределять на другое соединение до тех пор, пока не останутся такие остатки.

Ргдс, Мартин

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