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

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.007 c
15-1298266795
Лун
2011-02-21 08:39
2011.06.12
Облегчить беспорядок


15-1298541431
И. Павел
2011-02-24 12:57
2011.06.12
Как явно привести тип массива в яве?


6-1237807196
FireMan_Alexey
2009-03-23 14:19
2011.06.12
Вопрос по НТТР


2-1299212434
smart
2011-03-04 07:20
2011.06.12
Считывание значений из xml


2-1299002115
rodionov_uv
2011-03-01 20:55
2011.06.12
имя компонента