Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2011.06.12;
Скачать: [xml.tar.bz2];

Вниз

ClientSocket + TThread = ошибка при завершении программы   Найти похожие ветки 

 
Alex_C   (2009-03-24 09:27) [0]

В продолжении моей темы о работе телнет-сокета.
Чтоб работа телнет не тормозила работу основной программы, сокет был вынесен в отдельный тред.

собственно вот код:


constructor TTelnetThread.Create;
begin
 // Создаем сокет телнета
 TelnetSocket := TClientSocket.Create(nil);
 TelnetSocket.OnConnecting := ClientOnConnecting;
 TelnetSocket.OnConnect := ClientOnConnected;
 TelnetSocket.OnDisconnect := ClientOnDisconnected;
 TelnetSocket.OnRead := ClientOnRead;
 TelnetSocket.OnError := ClientOnError;
 inherited Create(false);
end;

destructor TTelnetThread.Destroy;
begin
 TelnetSocket.Free;
 inherited;
end;

procedure TTelnetThread.Execute;
begin
 FreeOnTerminate := True;
 try
   TelnetSocket.Host := NextHost;
   TelnetSocket.Port := NextPort;
   TelnetSocket.Service := "telnet";
   TelnetSocket.Active := True;
   while TelnetSocket.Socket.Connected do
    Application.ProcessMessages;
 finally
   TelnetSocket.Socket.Close;
 end;
end;


Проблема в том, что если попытаться закрыть программу во время работы сокета велетает ошибка чтения по адресу 0000000.
Вопрос: как корректно завершить соединение с сокетом, а затем закрыть программу?


 
Alex_C   (2009-03-24 10:18) [1]

В общем задача решена :)
Оказвается я перед закрытием программы делал вот что:



FormClose:

if Assigned(TelnetThread) then
begin
 TelnetThread.Disconnect; // Socket.Close
 TelnetThread.Free; // Тут ошибка и возникала, т.к. TelnetThread уже завершился!
end;



 
Palladin ©   (2009-03-24 10:23) [2]


>    while TelnetSocket.Socket.Connected do     Application.
> ProcessMessages;

а вот это зачем?


 
Palladin ©   (2009-03-24 10:24) [3]


>  FreeOnTerminate := True;

а это какого фика в Execute делает?


 
Palladin ©   (2009-03-24 10:24) [4]


>  finally    TelnetSocket.Socket.Close;  end;

а это зачем в Execute? разве при TelnetSocket.Free он не закрывается?


 
Palladin ©   (2009-03-24 10:25) [5]

короче бред какой то...


 
Slym ©   (2009-03-25 10:22) [6]

Palladin ©   (24.03.09 10:25) [5]
+1000
Неблокирующий сокет в потоке :)
Alex_C   (24.03.09 9:27)
сокет был вынесен в отдельный тред

ничего не вынесено... поток ничем особым и полезным не занимается


 
Palladin ©   (2009-03-25 10:44) [7]

... ах, он еще и неблокирующий... :)


 
Alex_C   (2009-03-25 12:46) [8]


> >    while TelnetSocket.Socket.Connected do     Application.
>
> > ProcessMessages;
>
> а вот это зачем?


Пока есть соединение - ожидаем ответа. А как правильно?


> >  FreeOnTerminate := True;
>
> а это какого фика в Execute делает?

А почему б ему тут не стоять? Есть разница где его размещать - в Create или Execute?


> >  finally    TelnetSocket.Socket.Close;  end;
>
> а это зачем в Execute? разве при TelnetSocket.Free он не
> закрывается?


ВЕЗДЕ написано, что закрывать сокет надо именно
TelnetSocket.Socket.Close
а не
TelnetSocket.Free


 
Palladin ©   (2009-03-25 13:04) [9]


> Пока есть соединение - ожидаем ответа. А как правильно?

Какого нахрен ответа, он у тебя никаких ответов не ждет, он у тебя воздух гоняет и тормозит все приложение.


> Чтоб работа телнет не тормозила работу основной программы

С каких фигов у тебя "работа телнет" тормозит основную программу если у тебя сокет не блокирующий, чего ты бредишь?  Зачем тебе отдельный поток? Воздух на самосвалах возишь?


> А почему б ему тут не стоять? Есть разница где его размещать
> - в Create или Execute?

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


> ВЕЗДЕ написано, что закрывать сокет надо именноTelnetSocket.
> Socket.Closeа неTelnetSocket.Free

Ну вот этого я не знаю, потому ничего не скажу. Может я и не прав.


 
Slym ©   (2009-03-25 13:04) [10]

Alex_C   (25.03.09 12:46) [8]
Пока есть соединение - ожидаем ответа. А как правильно?

правильно использовать боп поток при блокирующем режиме сокета (ClientType =  ctBlocking)
а у тебя ctNonBlocking
при ctBlocking не используются события типа:
TelnetSocket.OnConnecting
TelnetSocket.OnConnect
TelnetSocket.OnDisconnect
TelnetSocket.OnRead
TelnetSocket.OnError

пример работы в блокирующем режиме рассмотрен тут http://delphimaster.net/view/6-1227604925/


 
Сергей М. ©   (2009-03-25 13:12) [11]


> Alex_C   (25.03.09 12:46) [8]
>
>


Обращение к VCL-объектам в доп.потоке небезопасно, а в большинсве случаев и недопустимо.


 
Alex_C   (2009-03-25 14:18) [12]

Ок! Спасибо!
С сокетами вообще мало дело имел, а в тредах вообще.
Разобрался!
правильно для бликирующего сокета будет так:


       DataLength := TelnetSocket.Socket.ReceiveLength;
       Buf := GetMemory(DataLength);
       while TelnetSocket.Socket.Connected do
       begin
         Size := TelnetSocket.Socket.ReceiveBuf(Buf, DataLength);
         if Size <= 0 then
           Continue;
         ReadDataFromTelnet(Buf, Size);
       end;


где ReadDataFromTelnet - альнейшая обработка полученных данных.
Я правильно понимаю?


 
Alex_C   (2009-03-25 14:35) [13]

Поторопился.
Вот так правильно:

       while TelnetSocket.Socket.Connected do
       begin
         DataLength := TelnetSocket.Socket.ReceiveLength;
         if DataLength <= 0 then
           Continue;
         SetLength(Buf, DataLength);
         TelnetSocket.Socket.ReceiveBuf(Buf[0], DataLength);
         ReadDataFromTelnet(Buf, DataLength);
       end;


 
Сергей М. ©   (2009-03-25 14:46) [14]


> правильно понимаю?


Не совсем.

1. Вызов ReceiveLength в блокирущем режиме не обязателен - логика его использования более уместна в неблок.режиме с асинхронными нотификациями (ClientType = ctNonBlocking)

2. Результат вызова ReceiveBuf следует интерпретировать след.образом:

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

= 0 - удаленный партнер по соединению корректно разорвал соединение по своей инициативе. Continue тут также лишен смысла, следует закругляться.

> 0 - из вх.очереди актуально выбрано Size байт, можно их обрабатывать, при этом соединение на этот моменьт может уже и не существовать, будучи разорванным по тем или иным причинам.


 
Alex_C   (2009-03-25 16:28) [15]


> Не совсем.


Ок! Понял - буду разбираться дальше!



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

Форум: "Сети";
Текущий архив: 2011.06.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.004 c
2-1296798910
ZeaL
2011-02-04 08:55
2011.06.12
как установить связь по протоколу UDP с сервером движков hl (cs


3-1260431182
fd979
2009-12-10 10:46
2011.06.12
Проблема BDE и tnsnames.ora


2-1299263954
Филька
2011-03-04 21:39
2011.06.12
Windows 7 и плавное перемещение прогрессбара


15-1298033535
oxffff
2011-02-18 15:52
2011.06.12
Языки и циклические зависимости между блоками компиляции(units)


15-1296229392
madmech
2011-01-28 18:43
2011.06.12
Перестала работать среда разработки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский