Как мне отключить TcpClient, чтобы разрешить новые подключения? - PullRequest
1 голос
/ 28 января 2011

У меня есть TcpListener, который ждет новых соединений сокетов.Когда устанавливается новое соединение, некоторый другой код обслуживает сообщения от удаленного пользователя.Я периодически проверяю наличие новых подключений, и если создается новое, старое должно быть удалено.

Ранее я просто открывал новое подключение, которое по большей части работало нормально.Однако иногда у меня возникали проблемы с повторным использованием одного и того же порта, поэтому я решил, что было бы лучше закрыть это соединение (что, я думаю, должно также дать старому пользователю указание на то, что соединение прервалось).

приведенный ниже код является моей попыткой сделать это, но по какой-то причине вызов Disconnect блокируется на неопределенный срок.Есть ли способ остановить это?... или я что-то здесь упускаю?

while(1)
{
    // FYI, m_server is a TcpListener^ and m_client is a TcpClient^
        // Check for new client connections
    if (m_server->Pending() == true)
    {
        if( m_stream != nullptr )
        {
            m_client->Client->Shutdown( SocketShutdown::Both ); // Stop sending / receiving
            m_client->Client->Disconnect(true); // Disconnect the underlying network stream
            m_client->Client->Close(); // Disconnect the underlying network stream
            m_client->Close();
            delete m_client;
            m_client = nullptr;
        }

        m_client = m_server->AcceptTcpClient(); //grab the TCP client
        m_stream = m_client->GetStream();  //create the stream at the same time
    }

    // ...go and service pending messages on the client stream
}

Документы по функции Disconnect () предполагают, что я могу установить время ожидания, но они не упоминают как?

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

[Edit] Я нашел решение дляпроблема тайм-аута при изменении m_client->Client->Disconnect(true); на m_client->Client->Disconnect(false);, но это все равно не предупреждает моего клиента, что сокет закрыт.Я перепробовал все, что мог придумать, чтобы проверить, но все они успешны:

// m_client is a TcpClient^
bool stillConnected = ( (m_client != nullptr) &&
                        (m_client->Connected == true) &&
                        (m_client->Client != nullptr) &&
                        (m_client->Client->Connected == true) );

stillConnected всегда верно, даже после того, как другой клиент подключился к серверу и, следовательно, вызвал все биты выключения и куски выше,Это как отключение, которое я упомянул в начале моего вопроса, неправильно закрывает сокет или что-то в этом роде?

1 Ответ

1 голос
/ 29 января 2011

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

...