Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

Корректное завершение работы TIdTCServer


Oltas ©   (16.05.11 10:03

Здесь находил вопросы по этому поводу, но решения в них не было...  Если повтор или не нужно - удалите, пожалуйста...

Вот решение вопроса... Во всяком случае у меня работает.

Для самого компонента IdTcpServer нужно кинуть на форму еще элемент IdThreadMgrDefault1 и указать его в соответствующем пункте сервера в последней строке - TreadMgr.

Если после коннекта обращение клиента к серверу происходит в стандартной процедуре IdTCPServer1Executeвот так:
S:=Trim(AThread.Connection.ReadLn()); //где S:String;
то в момент, когда поток прерывается не по инициативе клиента, а аварийно, возникает исключение 10054Ю которое можно обработать тут же и перейти к процедуре уничтожения потока (у меня она: TcpServerTerminateAllThreads)

procedure TFServer.IdTCPServer1Execute(AThread: TIdPeerThread);
var
begin
if (AThread.Terminated) or (not AThread.Connection.Connected) then Exit;
 try
 S:=Trim(AThread.Connection.ReadLn());
 except
 if GetLastError=10054 then
    begin
    TcpServerTerminateAllThreads(AThread);
    Exit;
    end;
 end;
end;

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

procedure TFServer.TcpServerTerminateAllThreads(Tr: TIdThread);
var
I: Integer;
begin
if Tr = nil then
  begin
       with IdThreadMgrDefault1.ActiveThreads.LockList do
       try
       for I:=Count-1 downto 0  do
           begin
           Tr:=TIdThread(Items[I]);
           Tr.Terminate;
           Remove(Tr);
           end;
       finally
       IdThreadMgrDefault1.ActiveThreads.UnLockList;
       end;
  end else
  begin
       with IdThreadMgrDefault1.ActiveThreads.LockList do
       try
       Tr.Terminate;
       Remove(Tr);
       finally
       IdThreadMgrDefault1.ActiveThreads.UnLockList;
       end;
  end;
end;


У меня при выключении сервера эта процедура вызывается если не удалось штатно завершить работу сервера:

var
fServerRunning :Boolean;  //глобальная переменная

function TFServer.StopServer: Boolean;
begin
try
try
IdTCPServer1.Active := False;
except
end;
finally
IdTCPServer1.Bindings.Clear;
Result := not IdTCPServer1.Active;
fServerRunning := not Result;
end;
end;

procedure TFServer.checkbox_ServerActiveClick(Sender: TObject);
var
StopedYes Label;
begin
if checkbox_ServerActive.Checked then
  begin
  //при включении
  end else  
  begin
  if not StopServer then
           begin
           TcpServerTerminateAllThreads(nil); //вызов процедуры уничтожения потоков (nil у меня значит всех)
           //потом проверяем и еще раз пытаемся выключить сервер:
           if not StopServer then
           Memo1.Lines.Insert(0,'Ошибка остановки сервера'+DateTimeToStr(Now))
           else Goto StopedYes;
           end else
           begin
           StopedYes:
           //если сервер отключился пишем об этом например в TMemo
           Memo1.Lines.Insert(0,'Disconnect ###  '+DateTimeToStr(Now));
           end;
  end;
end;

procedure TFServer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
TcpServerTerminateAllThreads(nil);
Sleep(1000);
if fServerRunning then checkbox_ServerActive.Checked:=False; //вызываем процедуру отключения сервера
end;



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

Многое взято из примера сервера Indy8. Пока все это работает и потоки уничтожаются и при аварийном отрубании клиента и при "насильственном" завершении потоков при выключении...


Oltas ©   (16.05.11 20:03[1]

Простите - не в форуме Сеть выложил...


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо