Сокет. Близко действительно не закрывает сокет tcp? (c#)

Это кажется тем сокетом использования. Близко () для сокета tcp, не делает полностью близко сокета. В следующем примере я пытаюсь соединиться с example.com в порте 9999, который не открыт, и после короткого тайм-аута, я пытаюсь закрыть сокет.

  for (int i = 0; i < 200; i++)
  {
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    sock.LingerState = new LingerOption(false, 0);
    sock.BeginConnect("www.example.com", 9999, OnSocketConnected, sock);
    System.Threading.Thread.Sleep(50);
    sock.Close();
  }

Но когда я смотрю на netstat после того, как цикл завершается, я нахожу, что существует много полуоткрытых сокетов:

  TCP    israel-xp:6506         www.example.com:9999   SYN_SENT
  TCP    israel-xp:6507         www.example.com:9999   SYN_SENT
  TCP    israel-xp:6508         www.example.com:9999   SYN_SENT
  TCP    israel-xp:6509         www.example.com:9999   SYN_SENT

РЕДАКТИРОВАНИЕ. Хорошо, некоторый контекст отсутствовал. Я использую beginconnect, потому что я ожидаю, что сокетное соединение перестанет работать (9999, не открыт), и в моем реальном коде, я называю сокет. Близко (), как только таймер установлен. На OnSocketConnected я называю EndConnect, который выдает исключение (пытающийся назвать метод склонного объекта). Моя цель имеет короткий тайм-аут для этапа сокетного соединения.

Какая-либо подсказка, что я делаю неправильно? Спасибо!

11
задан r0u1i 6 January 2010 в 18:18
поделиться

4 ответа

Закрывает .NET-часть разъема. Однако, согласно спецификации TCP, операционная система должна держать лакомые кусочки нижнего уровня сокета открытыми в течение определённого времени для обнаружения ретрансляции и тому подобного. В этом конкретном случае, скорее всего, необходимо некоторое время держать сокет открытым для обнаружения ответа на отправленный SYN-пакет, чтобы он мог отвечать более разумно и не путать ответ с последующими отправленными пакетами

.
14
ответ дан 3 December 2019 в 01:20
поделиться

По конструкции, вы всегда должны вызывать Shutdown перед закрытием сокета.

mySocket.Shutdown(SocketShutdown.Both);
mySocket.Close();

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

Jon Skeet также имеет точку зрения, что так как вы открываете соединение асинхронно, оно может на самом деле соединяться, когда вы пытаетесь его закрыть. Однако, если вы позвоните Shutdown на него, он не позволит получить информацию в то время, как вы испытываете.

Edit: Вы можете только Shutdown сокетом, который уже подключен, так что имейте это в виду, пока вы пишите свой код.

.
18
ответ дан 3 December 2019 в 01:20
поделиться

Вы вызываете *Начать*Соединение - поэтому делаете это асинхронно. Вполне возможно, что вы пытаетесь закрыть сокет еще до того, как он будет подключен - так что когда он будет подключен, он останется открытым.

Попробуйте подключиться синхронно - или закрыть его в OnSocketConnected, чтобы увидеть эффект от закрытия действительно подключенного сокета.

.
10
ответ дан 3 December 2019 в 01:20
поделиться

Вы инициализируете новый сокет в каждом цикле... с помощью *.close() вы закрываете старый и в начале создаете новый с теми же параметрами, что и предыдущий сокет.

.
0
ответ дан 3 December 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: