Завершение TCP-сервера Indy10

Я использовал Indy с C ++ Builder XE3. Это идеальная система, но у меня есть некоторые проблемы. IdTCPServer работает очень хорошо, но когда у меня есть несколько подключений к нему, и я хочу остановить сервер, мое приложение зависло. Я пытаюсь рассказать, как я делаю это шаг за шагом:
1) Запуск приложения (и прослушивание сервера)
2) дождаться новых подключений (или смоделировать, без разницы)
3) когда у нас 10-15 подключений — попробуйте остановить прослушивание сервера.
4) когда код пришел к IdTCPServer1-> Active = false — приложение будет заморожено

Я сделал небольшое видео. Может быть, это объясняет ситуацию намного лучше. http://www.youtube.com/watch?v=BNgTxYbLx8g

И вот мой код:

OnConnect:

EnterCriticalSection(&CritLock);
++ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);

OnDisconnect:

EnterCriticalSection(&CritLock);
--ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);

Код StopServer:

void TForm1::StopServer()
{
TList *list = IdTCPServer1->Contexts->LockList();
try
{
for(int i = 0; i < list->Count; ++i)
{
TIdContext *AContext = reinterpret_cast<TIdContext*>(list->Items[i]);
try
{
if (AContext->Connection->Connected())
{
AContext->Connection->IOHandler->InputBuffer->Clear();
AContext->Connection->IOHandler->WriteBufferCancel();
AContext->Connection->IOHandler->WriteBufferClear();
AContext->Connection->IOHandler->WriteBufferClose();
AContext->Connection->IOHandler->CloseGracefully();
AContext->Connection->Disconnect();
}
}
catch (const Exception &e)
{

}
}
}
__finally
{
IdTCPServer1->Contexts->UnlockList();
}
IdTCPServer1->Contexts->Clear();
//IdTCPServer1->StopListening();
IdTCPServer1->Active = false;
}

Спасибо за совет!

0

Решение

Вам нужно избавиться от всех ваших StopServer() код, за исключением самой последней строки. когда TIdTCPServer деактивирован, он выполняет все необходимые очистки для вас. НЕ ДЕЛАЙТЕ ЭТОГО СЕБЯ (тем более, что ты все равно делаешь неправильно).

void TForm1::StopServer()
{
IdTCPServer1->Active = false;
}

Теперь, имея только этот код, если ваше приложение все еще зависает, это означает, что вы блокируете основной поток. Это произойдет, если вы позвоните StopServer() в контексте основного потока и одна из двух вещей происходит в коде вашего сервера:

  1. один из ваших TIdTCPServer Обработчики событий выполняют синхронизированную операцию с основным потоком (либо через TIdSync или же TThread::Synchronize()).

  2. один из ваших TIdTCPServer обработчики событий проглатывает Indy исключения и не позволяет TIdTCPServer правильно завершить один или несколько клиентских потоков при необходимости.

Внутренне TIdTCPServer::Active установщик свойств закрывает все активные сокеты и ожидает полного завершения их соответствующих потоков, блокируя вызывающий поток до выхода из установщика свойства. Если вы деактивируете сервер в главном потоке, и один из потоков сервера выполняет синхронизацию, которую основной поток не может обработать, или иначе не завершается корректно, когда это должно быть, это заблокирует деактивацию сервера от выхода и, таким образом, заблокирует основной нить.

Поэтому убедитесь, что:

  1. Вы не выполняете операции синхронизации с основным потоком, пока сервер отключается основным потоком. Если вам необходимо выполнить синхронизацию, то деактивируйте сервер в рабочем потоке, чтобы основной поток больше не блокировался.

  2. ваши обработчики событий не глотают инди EIdExceptionисключения в try/catch блоки. Если вы поймали такое исключение, перебросьте его, когда вы закончите, используя его. Позволять TIdTCPServer обрабатывать любые исключения Indy, чтобы он мог выполнять внутреннюю очистку по мере необходимости.

Наконец, отметим, что вам не нужно отслеживать соединения вручную. TIdTCPServer уже делает это для вас в Contexts имущество. Если вам нужно знать, сколько клиентов в данный момент подключено, просто Lock() Contexts список, прочитайте его Count собственности (или делать что-либо еще, что вам нужно сделать с клиентами), а затем Unlock() список.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]