Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.03.06;
Скачать: CL | DM;

Вниз

Обработка ошибки 10061, TClientSocket   Найти похожие ветки 

 
Delpher_Gray   (2004-12-30 07:37) [0]

Добрый день, Мастера !
Пишу многопотоковую программу, использующую TClientSocket. В клиент-сокете на событие ошибки - OnError, чтоб не вылазило ошибок я написал "ErrorCode := 0;". Но всё-же тут иногда возникает ошибка 10061 ! С чём она связана и как её обработать чтоб подобного не повторялось ?
Программа вообще должна работать автоматически, а тут эта ошибки иногда выскакивает... Если Ок не нажать все потоки стают...

Заранее благодарен.


 
Digitman ©   (2004-12-30 08:14) [1]

http://delphimaster.net/view/6-1104233111/


 
Delpher_Gray   (2004-12-30 08:47) [2]

Я ведь сразу сказал что в OnError строка "ErrorCode := 0;" у меня есть.
Тут ошибка возникает ещё до события OnError. По-моему сразу после открытия сокета. Например когда у меня инет отключён, а я пытаюсь подрубиться вот тогда - 10061. Пробывал впихнуть Sock.Open в try...except, всё-равно вылазит...

procedure TMyThread.Execute;
begin
 Sock := TClientSocket.Create(nil);

 // тут настраиваю порт и хост, проверяю юзатется ли прокси

 Sock.ClientType := ctNonBlocking;
 Sock.OnConnect := SockConnect;
 Sock.OnDisconnect := SockDisconnect;
 Sock.OnError := SockError;
 Sock.OnRead := SockRead;
 Synchronize(Sock.Open);
end;


Вот...


 
Digitman ©   (2004-12-30 10:58) [3]

procedure TMyThread.Execute;
var
 Msg: TMsg;
begin
try
//создаем гнездо
 Sock := TClientSocket.Create(nil); //по дифолту режим уже ctNonBlocking, явно устанавливать его не нужно
 try
  // тут настраивай св-ва Host, Port и т.д.
  Sock.OnConnect := SockConnect;
  Sock.OnDisconnect := SockDisconnect;
  Sock.OnError := SockError;
  Sock.OnRead := SockRead;
  Sock.Open; //стартуем асинхронную операцию коннекта

//*****************************************************
//** цикл ожидания/выборки/диспетчеризации сообщений **
//*****************************************************

//пока трэду не было команды закругляться по хозяйству
//ожидаем сообщения в очереди сообщений текущего трэда

  while not Terminated and GetMessage(Msg, 0, 0, 0) do
   if Msg.hWnd = 0 then
//здесь диспетчеризуем сообщения, адресованные непосредственно трэду, если они имеются
     Dispatch(Msg.Message)
   else
//а здесь диспетчеризуем сообщения, адресованные окнам, созданным текущим трэдом, в т.ч. и в 1-ю очередь - окну, созданному классом TClientWinSocket для приема нотиф.сообщений гнезда о происходящих транспортных событиях и ошибках
     DispatchMessage(Msg);
 finally
//бузусловно уничтожаем гнездо
  Sock.Free;
 end;
except
//здесь, если нужно, протоколируем все возникшие в ходе работы трэда незапланированные искл-я
//и ни в коем случае не плодим новые !!! иначе - кирдык
end;
end;

procedure TMyThread.Destroy;
begin
 if GetCurrentThreadId <> ThreadId then
   PostThreadMessage(ThreadId, WM_QUIT, 0, 0);
 inherited;
end;

Вот...


 
Digitman ©   (2004-12-30 11:08) [4]

главная твоя ошибка - в непонимании того что в ходе исполнения Open() создается невидимое окно, которое будет "принадлежать" трэду, вызвавшему этот метод .. в твоем случае (см.Synchronize) это будет основной трэд (зачем, спрашивается ?), он же как "владелец" созданного окна и обязан после этого принимать и диспетчеризовать оконные сообщения, посылаемые гнездом .. НО ! .. запустив асинхр.операцию коннекта ты тут же завершаешь работу трэда и, вероятно, следом уничтожаешь объект MyThread, что вообще недопустимо, ибо ты назначит методы этого объекта в кач-ве обработчиков событий гнезда


 
Delpher_Gray   (2004-12-30 12:11) [5]

а вот теперь код проги приведу:

procedure TMyThread.Execute;
var
 Msg: TMsg;
begin
 try
   Sock := TClientSocket.Create(nil);
   try
     //хост и порт

     Sock.OnConnect := SockConnect;
     Sock.OnDisconnect := SockDisconnect;
     Sock.OnError := SockError;
     Sock.OnRead := SockRead;
     Sock.Open;

   while not Terminated and GetMessage(Msg, 0, 0, 0) do
     if Msg.hWnd = 0 then
      Dispatch(Msg.Message)
     else
      DispatchMessage(Msg);
   finally
      Sock.Free;
   end;
 except
   NextOpp;
 end;
end;

destructor TMyThread.Destroy;
begin
 if GetCurrentThreadId <> ThreadId then
   PostThreadMessage(ThreadId, WM_QUIT, 0, 0);
 inherited;
end;

procedure TMyThread.SockConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
 // тут шлю HTTP заголовки
end;

// тут читаю данные с гнезда. Это ведь HTTP, читаю до отключения.... Header и Content - это TStringList"ы.

procedure TMyThread.SockRead(Sender: TObject; Socket: TCustomWinSocket);
var
 EndPos: integer;
begin
 if HeaderReceive then
 begin
   Header.Text := Header.Text+Socket.ReceiveText;
   EndPos := Pos(#13#10#13#10, Header.Text);

   if EndPos > 0 then
   begin
     Content := TStringList.Create;
     Content.Text := Copy(Header.Text, EndPos+4,
       Length(Header.Text)-EndPos-4);

     Header.Text := Copy(Header.Text, 1, EndPos);

     HeaderReceive := false;
   end;
 end else
   Content.Text := Content.Text+Socket.ReceiveText;
end;

procedure TMyThread.SockDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
 // выполняю действия с полученными данными

 NextOpp; // След. операция
end;

procedure TMyThread.SockError(Sender: TObject; Socket: TCustomWinSocket;
 ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
 ErrorCode := 0;

 NextOpp;
end;

procedure TMyThread.NextOpp;
begin
 // вот тут выполняется следующая операция.
 Sock.Close;
 // настраивается порт и хост и заного
 Sock.Open;
end;


Всё ли верно ? А систему мне нада подучить срочно :( Чтож, займусь...


 
Delpher_Gray   (2004-12-30 12:15) [6]

а вот ошибка у меня...
try
 Sock := TClientSocket.Create(nil);
 ...
except
 // NextOpp; // !!!

 // тут ведь нужно или ничего не делать чтоб поток сам уничтожился, или поменять хост и порт и попробывать снова так ведь ?
end;


 
Digitman ©   (2004-12-30 12:44) [7]


> Всё ли верно ?


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


> Delpher_Gray   (30.12.04 12:15) [6]


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


 
Delpher_Gray   (2004-12-30 12:55) [8]


> будет вызван твой обработчик SockError.. вот в нем- то ,
> очевидно, и следует рестартовать механизм повторного коннекта
> с измененными параметрами


Ну вот там как раз и выполняется NextOpp;


> поэтому бессмысленно в обработчике искл-я пытаться выполнять
> реконнект - объект-то не создан


Так... В даннй ситуации возможен ли такой вариант что первый раз сокет не создавля, а при второй попытке создался ??
В моей программер нужно сделать N"е кол-во операций. Что мне делать в этой ситуации ? Тормознуть все потоки или попробывать ещё раз (выполнить Execute) ?


 
Digitman ©   (2004-12-30 13:06) [9]


> В даннй ситуации возможен ли такой вариант что первый раз
> сокет не создавля, а при второй попытке создался ??


все что угодно может быть .. нужно анализировать конкретные причины искл-я, возникшего при конструировании объекта, и по результатам анализа уже принимать решение .. например, если искл-е говорит об "Out of memory" (что крайне маловероятно при грамотном подходе к распределению памяти), бессмысленно повторять попытки конструирования


 
Delpher_Gray   (2004-12-30 13:43) [10]

А вот такой теперь вопрос...
Почему если в NextOpp"е не создаётся заного сокет - Sock := TClientSocket.Create(nil), то подключения нет ??
Да и как он может таким образом созжаваться, когда он не освобождается ? или всё верно, так и должно быть... !?

NextOpp:
Sock := TClientSocket.Create(nil);
....
....
....
Sock.Open;


 
Delpher_Gray   (2004-12-30 15:32) [11]

ауу...


 
Digitman ©   (2004-12-30 15:36) [12]


> Почему если в NextOpp"е не создаётся заного сокет - Sock
> := TClientSocket.Create(nil), то подключения нет ??


откуда ж оно возьмется ? если ты не создал объект, реализующий логику подключения ?


> Да и как он может таким образом созжаваться, когда он не
> освобождается ?


так ... стоп ... мы тут о чем вообще ?
о создании некоего VCL-объекта или о логике исполнения некоего метода УЖЕ СУЩЕСТВУЮЩЕГО VCL-объекта ?
причем неважно какого метода - коннект делающего или что-то еще ?


 
Delpher_Gray   (2004-12-30 15:59) [13]


> откуда ж оно возьмется ? если ты не создал объект, реализующий
> логику подключения ?


Ну ведь у меня есть сокет, и я пытаюсь переставить Host и Port и заного открыть сокет. Невыходит, а почему ?


 
Digitman ©   (2004-12-30 16:29) [14]


> Delpher_Gray   (30.12.04 15:59) [13]



> Ну ведь у меня есть сокет


дык, ешкин кот, ты ж его получил УСПЕШНЫМ вызовов конструктора ?


> я пытаюсь переставить Host и Port


КАКОГГО объекта ? реально ли созданного и существующего ?


и заного открыть сокет


"открыть сокет", если я правильно "въехал" с т.з. ТРАДИЦИОННОЙ терминологии, сводится к вызову тобой некоего метода Open() некоего объекта класса-наследника TClientSocket

отсюда и вопрос - какое, нафих, отношение имеет вызов некоего метода объекта к факту НЕсоздания объекта этого самого класса ? ты можешь это прокомментировать ?


 
Delpher_Gray   (2004-12-30 16:40) [15]

Что-то я совсем запутался =)
Сокет (Sock) уже существоет создавать его не нужно, так ?
Теперь я пытаюсь сделать Sock.Open, ведь в момент выполнения открытия сокета, соединения нет, т.к. открываю я заного сокет на событии OnDisconnect.
Вобщем как правильно сделать ?


 
Digitman ©   (2004-12-30 16:51) [16]


> Сокет (Sock) уже существоет создавать его не нужно, так ?


так.


> Теперь я пытаюсь сделать Sock.Open


да.


> в момент выполнения открытия сокета


определись, что ты подразумеваешь под "открытием сокета" ?


 
Delpher_Gray   (2004-12-30 17:07) [17]

ну ведь сокет открыть/активировать можно только:
Sock.Open();
Sock.Active := true;

или подругому нужно делать ?


 
Digitman ©   (2004-12-30 17:14) [18]

да.

именно так.
но ведь ты в [8] и [10] завел речь отнюдь не о вызове метода объекта и не об обращении к его св-ву ! А о создании объекта как такового ..
Одно из 2-х - либо ты не в состоянии сформулировать вопрос кратко и внятно, либо у меня уже началось празднование НГ)


 
Delpher_Gray   (2004-12-30 17:21) [19]


> Одно из 2-х - либо ты не в состоянии сформулировать вопрос
> кратко и внятно, либо у меня уже началось празднование НГ)

:) Я и сам хочу уже праздновать, но нужно писать... Срочно =)
в [10] я привл пример, как будет работать. если в процедуре NextOpp будет код:
   //устанавливаю хосит и порт
   Sock.OnConnect := SockConnect;
   Sock.OnDisconnect := SockDisconnect;
   Sock.OnError := SockError;          
   Sock.OnRead := SockRead;  
   Sock.OnWrite := SockWrite;
   Sock.Open;

То после 1-го подключения дальше ничего не будет. Код выполнится а реакций на него нуль :( То есть никаких событий, ни OnConnect, ни OnDisconnect и т.п.
А если вставить строчку Sock := TClientSocket.Create(nil), то работает... Но строчку эту писать не нужно, уж без неё как-нибудь =)


 
Delpher_Gray   (2004-12-30 19:18) [20]

аууу...


 
Digitman ©   (2004-12-31 08:17) [21]

не понимаю, чего ты снова экспериментируешь ?)
чем тебе [3] не нравится ?


> То есть никаких событий, ни OnConnect, ни OnDisconnect


откуда ж они возьмутся, если коннекта реально не происходит из-за недоступности сервера ? .. ведь в этом случае будет вызвана SockError, где ты и "гасишь" ошибку, т.е. то самое что тебе и нужно было судя по первоначально сформулированной тобой задаче..



Страницы: 1 вся ветка

Текущий архив: 2005.03.06;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.062 c
4-1106306947
IronHawk
2005-01-21 14:29
2005.03.06
Приветствую! Всё о старом, TRANSPARENT формы, как?


1-1108897722
Kosald
2005-02-20 14:08
2005.03.06
Как сделать так, чтобы форма отображалась всегда поверх окон


1-1108806190
netmouse
2005-02-19 12:43
2005.03.06
DBGrid


1-1109056820
Hadroran
2005-02-22 10:20
2005.03.06
Чтение генератора из InterBase


1-1108972230
DimonS
2005-02-21 10:50
2005.03.06
Вопрос по временным промежуткам