-
Посоветуйте, пожалуйста, как проще всего отключиться от TCP-сервера (IdTCPServer1: TIdTCPServer;) не получая сообщений ClosedGracefully ? Мучаюсь уже 3-ий день, пробовал разные варианты, но сообщения эти все же появляются, может быть немного чаще или реже. У меня к серверу подключены 5 клиентов TIdTCPClient; К моменту отключения они не обмениваются сообщениями. Отключение произвожу со стороны клиента, при этом серверу ничего не сообщаю, надеясь, что он отключит соответствующие веточки. При этом клиент выполняет:
procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var comma,repa: string; begin if MessageDlg('Вы уверены, что хотите выйти из игры?'+#13#10+ '(не менее двух раз)', mtConfirmation,[mbYes, mbNo], 0) = mrNo then CanClose := False else begin TM1.Enabled:= false; if Client.Connected then begin Client.DisConnect; CanClose := False; end else CanClose:= True; end; end;
При 1-й попытке закрыть форму отключается таймер (который посылал команды на сервер) и отключается IdTCPClient при 2-й попытке - закрывается форма. сообщения ClosedGracefully появляются чаще при 2-й попытке, но бывают и при 1-й. Написано, что это сообщение возникает, если соединение закрыто с другой стороны, а клиент пытается что-то прочесть или записать.
Идея с 2-я попытками - отладочная, попытка что-то понять, но пока ни просвета.
-
unit idStak; procedure TIdStack.RaiseSocketError(const AErr: integer);
begin
(*
RRRRR EEEEEE AAAA DDDDD MM MM EEEEEE !! !! !!
RR RR EE AA AA DD DD MMMM MMMM EE !! !! !!
RRRRR EEEE AAAAAA DD DD MM MMM MM EEEE !! !! !!
RR RR EE AA AA DD DD MM MM EE
RR RR EEEEEE AA AA DDDDD MM MM EEEEEE .. .. ..
Please read the note in the next comment.
ну так плиз, рид зе ноте ин зе некст коммент.
-
Спасибо, попробую найти и почитать FAQ, однако боюсь, что утону там :-((
-
-
я тоже по той ссылке не ходил. когда получил свой первый грэйсфул клозет. мне хватило коментария в самом модуле начало которого приведено выше.
-
> Winni (30.11.2010 23:52:00) [0]
Никак, можно только не показывать. Это нормальный разрыв связи, нету потока данных/команд и другая сторона просто разорвет соединение и это не ошибка.
-
Спасибо.
Да, я тоже читал, что это нормально, но все-таки наверное, не совсем, ибо нажимать до 50 раз на ОК этого окошка все же не нормально. А как можно не показывать ? Я пытался сообразить, в каком месте поставить try , но не сообразил, ибо нет вроде бы чтения-записи в это время. Видимо, придется один из клиентов запустить в Делфи, в режиме отладки.
Забавно, что при числе клиентов < 4 это не возникает и при отключении первых двух тоже. Не поленился вклинить между клиентом и сервером SocketSpy и увидел, что сообщения эти не сопровождаются передачей чего либо по сети. Но вот что непонятно: вроде бы клиент не передает и не читает что-либо из соединения. То есть нет причины ему возмущаться. Почитаю внимательнее рекомендуемый комментарий, может что дойдет.
-
ибо нажимать до 50 раз на ОК
Ты выбирай. Либо прокачивай пальцы, кликая на Ок, либо прокачивай знания, читая основы языка. Обработку там всяких исключений и прочие конструкции.
-
Читай FAQ, смотри примеры.
-
Нашел, однако. Действия readln,writeln в соединение, запущенные таймером, продолжались, естественно какое то время после остановки таймера. А у меня (см выше ) сразу после остановки таймера стоит disconnect (без разрыва во времени). И кроме того, эти readln,writeln не были заключены в try.. except но это проглядел, каюсь. А то бы увидел - где это происходит.
Теперь добавил 2-й таймер. Получается так:
procedure TFormMain.N3Click(Sender: TObject); begin if MessageDlg('Вы уверены, что хотите выйти из игры?', mtConfirmation,[mbYes, mbNo], 0) = mrYes then begin TM1.Enabled:= false; TM2.Enabled:= true; end; end;
procedure TFormMain.TM2Timer(Sender: TObject); begin TM2.Enabled:= false; if Client.Connected then begin try Client.DisConnect; except on E: EIdException do begin showmessage('MyErrorDisConnect'); end; end; end; if not Client.Connected then Application.Terminate; end;
хотя обычно DisConnect не заключают в блок try и это можно выкинуть и расслабиться. Спасибо за поддержку. Тяжелая артиллерия не понадобилась :-))
-
Рано обрадовался. После переделок программы проблема вернулась. Похоже, что нужно это исключнение вообще игнорировать, т е
try .... except on E: EIdConnClosedGracefully do begin // nothing end; on E: EIdException do begin showmessage('Ошибка: таймер, №1'+ E.Message); end; end;
Этого тсключения теперь не видно, но часто виснет этот клиент. Все равно что-то не то и нужно искать.
-
try
....
except
on E: EIdException do
begin
showmessage('Ошибка: таймер, №1'+ E.Message);
end;
end;
-
Спасибо, попробую, если сохранил эту версию (сейчас у меня уже 8-я версия). То есть Вы хотите сказать, что сработают оба ON, а я думал, что как CASE, т е первая и сразу на выход. Но мне больше понравилось отключение со стороны сервера, т е клиент посылает 'QUIT', который сервер, прочитав строку, распознает как команду и закрывает эту веточку методом Disconnect. Хотел приблизится к описанному в Вашем переводе способу, когда сервер в ответ на эту команду отвечает клиенту что-нибудь, например 'bye' и сразу после этого Disconnect, а клиент, получив это 'bye' закрывает себя, т е Client.DisConnect . Но почему то не вышло и забросил я такой вариант. Вроде пока с этим проблем нет. Сейчас так:
procedure TFormMain.TM2Timer(Sender: TObject); begin TM2.Enabled:= false;
if Client.Connected then try Client.WriteLn('QUIT'); except on E: EIdConnClosedGracefully do begin // nothing end; on E: EIdException do begin showmessage('Ошибка: N3Click'+ E.Message); end; end;
Application.Terminate; end;
Хорошо бы иметь подборку примеров с тематическим оглавлением, наверное где-то он есть.
|