Socket.Close на самом деле не закрывает сокет TCP? (C #) - PullRequest
11 голосов
/ 06 января 2010

Кажется, что использование socket.Close () для 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

EDIT , Хорошо, некоторый контекст отсутствовал. Я использую beginconnect, потому что я ожидаю, что соединение с сокетом не будет установлено (9999 не открыт), и в моем реальном коде я вызываю socket.Close (), как только таймер установлен. На OnSocketConnected я вызываю EndConnect, который выдает исключение (пытаясь вызвать метод удаленного объекта). Моя цель - сократить время ожидания на этапе подключения к сокету.

Любая подсказка, что я делаю не так? Спасибо!

Ответы [ 4 ]

18 голосов
/ 06 января 2010

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

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

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

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

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

14 голосов
/ 06 января 2010

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

10 голосов
/ 06 января 2010

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

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

0 голосов
/ 06 января 2010

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

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