Блюз TcpListener, не могу понять, почему соединение не закрывается правильно

#.net #sockets

#.net #сокеты

Вопрос:

Мой TcpListener настроен следующим образом:

 this.tcpListener = new TcpListener(IPAddress.Any, config.portNum);
  

Затем я (используя потоковую обработку) настраиваю функцию прослушивания следующим образом:

 private void ListenForClients()
    {
       this.tcpListener.Start(); 

       while (true)
       {
         //blocks until a client has connected to the server
         TcpClient client = this.tcpListener.AcceptTcpClient();

         //create a thread to handle communication 
         //with connected client

         ThreadStart starter = delegate { HandleClientComm(client, this.DBGrid); };
         Thread thread = new Thread(starter);
         thread.Start();
        }
     }
  

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

Обычно допускается только одно использование каждого адреса сокета (протокол / сетевой адрес / порт)

Внутри потока есть вызов close:

 tcpClient.Close();
  

Но, похоже, это не освобождает порт, какие-либо предложения?

Комментарии:

1. Какова конкретная строка кода, для которой вы получаете exeception?

2. this.TcpListener. Start(); вызывает проблему во 2-й раз.

3. Вы вызываете TcpListener. Запуск более одного раза в одном и том же процессе или что, как только вы завершаете свой процесс и перезапускаете его, вы получаете ошибку?

Ответ №1:

Если вы вызываете ListenForClients его повторно, это является источником вашей проблемы, а не то, что клиентское соединение работает Close() неправильно.

Традиционно один поток обрабатывает открытие основного сокета и прием «дочерних» сокетов подключения. Таким образом, ваш ListenForClients должен быть в главном потоке сервера и вызываться только один раз для каждого приложения.

ЕЩЕ НЕМНОГО ИНФОРМАЦИИ:

 this.tcpListener.Start(); 
  

создает прослушивающее устройство, подключенное к указанному вами порту. С каждым подключением клиента,

 TcpClient client = this.tcpListener.AcceptTcpClient();
  

строка создаст НОВЫЙ подключенный сокет, который находится на совершенно другом порту. Таким образом, закрывая свой клиент, вы вообще не освобождаете свой основной сокет.

Из http://en.wikipedia.org/wiki/Internet_socket#Socket_states_and_the_client-server_model

Компьютерные процессы, предоставляющие службы приложений, называются серверами и создают сокеты при запуске, которые находятся в состоянии прослушивания. Эти сокеты ожидают инициатив от клиентских программ. Для прослушивающего TCP-сокета удаленный адрес, представленный netstat, может обозначаться 0.0.0.0, а номер удаленного порта 0.

TCP-сервер может обслуживать несколько клиентов одновременно, создавая дочерний процесс для каждого клиента и устанавливая TCP-соединение между дочерним процессом и клиентом. Для каждого соединения создаются уникальные выделенные сокеты. Они находятся в установленном состоянии, когда виртуальное соединение сокет-сокет или виртуальная схема (VC), также известная как сеанс TCP, устанавливается с удаленным сокетом, обеспечивая дуплексный поток байтов.

Ответ №2:

Проблема в TcpListener.Start() . Вам не разрешено иметь 2 прослушивателя на одном порту. Метод ListenForClients должен вызываться только один раз в вашем приложении