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

Вниз

TClientSocket в неблокирующем режиме   Найти похожие ветки 

 
vfb   (2006-05-26 08:02) [0]

Доброе утро!

Третий день пытаюсь понять, где я неправ. Посмотрите, пожалуйста, направьте на путь истинный :)

Я сделал маленький класс - наследник TClientSocket, который использую для загрузки данных. Но почему-то после события onDisconnect приложение начинает требовать 70-90% процессорного времени, при этом откуда-то берутся два потока (понятно, что это потоки TClientSocket-а, но почему они не "убиваются" - непонятно).

Вот несколько упрощенный класс:

unit libTCP;

interface

uses
 Classes, Windows, Messages, SysUtils, ScktComp, Forms, Dialogs, StdCtrls, Sockets, StrUtils;

Const
 WM_SOCKS_CONNECTING   = WM_USER+10;
 WM_SOCKS_CONNECTED    = WM_USER+11;
 WM_SOCKS_DISCONNECTED = WM_USER+12;
 WM_SOCKS_ERROR        = WM_USER+13;
 WM_SOCKS_SENDING      = WM_USER+14;
 WM_SOCKS_RECIEVING    = WM_USER+15;

type
 TSocksEvent = procedure (Sender: TObject) of object;
 TSocksEvent2 = procedure (Sender: TObject; str: string) of object;

 TSocks = class(TClientSocket)
 private
   FOnComplete: TSocksEvent;
   FForString : TSocksEvent2;
   encoded_request: string;
   bytes_left_to_send: integer;
 public
   FCommand   : string;
Answer     : ^string;
   MsgHandler : THandle;
   LogLabel   : TLabel;
   MemoLog    : TMemo;
   property  onComplete : TSocksEvent read FOnComplete write FOnComplete;
   property  onString   : TSocksEvent2 read FForString  write FForString;
   constructor Create(AOwner: TComponent); override;
   destructor  Destroy; override;
   procedure Execute;
   procedure _onRead(Sender: TObject; Socket: TCustomWinSocket);
   procedure _onWrite(Sender: TObject; Socket: TCustomWinSocket);
   procedure _onConnecting(Sender: TObject; Socket: TCustomWinSocket);
   procedure _onConnect(Sender: TObject; Socket: TCustomWinSocket);
   procedure _onDisconnect(Sender: TObject; Socket: TCustomWinSocket);
   procedure _onError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent : TErrorEvent; var ErrorCode: Integer);
end;

implementation

destructor TSocks.Destroy;
Begin
 inherited destroy;
end;

constructor TSocks.Create(AOwner: TComponent);
Begin
 inherited Create(AOwner);
 MsgHandler := 0;
 Answer     := nil;
 FCommand   := "";
 self.ClientType := ctNonBlocking;
 self.onConnecting := _onConnecting;
 self.onConnect    := _onConnect;
 self.onDisconnect := _onDisconnect;
 self.onRead       := _onRead;
 self.onWrite      := _onWrite;
 self.onError      := _onError;
end;

procedure TSocks.Execute;
Begin
 encoded_request:= FCommand;
 bytes_left_to_send := length(encoded_request);

 Self.Open;
 repeat Application.ProcessMessages until Self.Active;
end;

procedure TSocks._OnWrite(Sender: TObject; Socket: TCustomWinSocket);
Var sb: integer;
Begin
 if bytes_left_to_send > 0 then Begin
   sb := Socket.SendText(RightStr(encoded_request, bytes_left_to_send));
   bytes_left_to_send := bytes_left_to_send - sb;
 end;
end;

procedure TSocks._onRead(Sender: TObject; Socket: TCustomWinSocket);
Var str  : string;
   npos : integer;
   i    : integer;
Begin
 if MemoLog <> nil then MemoLog.Lines.Add("Recieved "+IntToStr(Socket.ReceiveLength)+" bytes");
 if Socket.ReceiveLength > 0 then begin
   str := Socket.ReceiveText;
   //Decode answer using the private Fkey
   Answer^ := Answer^ + str;
 end;
end;

procedure TSocks._onConnecting(Sender: TObject; Socket: TCustomWinSocket);
Begin
 if MsgHandler > 0 then PostMessage(MsgHandler, WM_SOCKS_CONNECTING, 0, 0);
 if MemoLog <> nil then MemoLog.Lines.Add("Connecting...");
end;

procedure TSocks._onConnect(Sender: TObject; Socket: TCustomWinSocket);
Begin
 if MsgHandler > 0 then PostMessage(MsgHandler, WM_SOCKS_CONNECTED, 0, 0);
 if MemoLog <> nil then MemoLog.Lines.Add("Connected");
end;

procedure TSocks._onDisconnect(Sender: TObject; Socket: TCustomWinSocket);
Var str: string;
Begin
 if Socket.ReceiveLength > 0 then begin
   str := Socket.ReceiveText;
   //
   Answer^ := Answer^ + str;
   if MemoLog <> nil then MemoLog.Lines.Add("Data recieved before disconnect");
 end else
   if MemoLog <> nil then MemoLog.Lines.Add("NO Data left before disconnect");

 Self.Close;
 if MsgHandler > 0 then PostMessage(MsgHandler, WM_SOCKS_DISCONNECTED, 0, 0);
 if Assigned(FOnComplete) then FOnComplete(Sender);
end;

procedure TSocks._onError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent : TErrorEvent; var ErrorCode: Integer);
Begin
 if MsgHandler > 0 then PostMessage(MsgHandler, WM_SOCKS_ERROR, 0, 0);
 if Assigned(FOnComplete) then FOnComplete(Sender);
 if MemoLog <> nil then MemoLog.Lines.Add("Error");
end;

end.

Всё это работает в DLL (в ней кроме этого класса - класс формы приложения + требуемый функционал). Но насколько я (не) понимаю, дело совсем даже не в DLL.


 
Сергей М. ©   (2006-05-26 08:19) [1]

Убери self.Close

И вообще во всех методах своего класса убери self - ни к чему он


 
vfb   (2006-05-26 08:24) [2]

Убрал (а Close поставил вообще от безысходности).
Но конечно, это ничего не поменяло.
Я могу и вызов показать, но думаю что и так максимально понятно :)


 
Сергей М. ©   (2006-05-26 08:40) [3]


> могу и вызов показать


Покажи...


 
vfb   (2006-05-26 13:21) [4]

Var tcp := TSocks;
    server_answer: string;
...
begin
 lvUsers.Items.Clear;
 tcp.FCommand := "GET USERLIST";
 tcp.Answer := @server_answer;
 tcp.Host := "freebsd.domain";
 tcp.Port := 7712;
 tcp.onComplete := RequestComplete; // procedure TfrmUsers.RequestComplete(Sender: TObject);
 tcp.onString := NewUserString; // procedure TfrmUsers.NewUserString(Sender: TObject; str: string);
 tcp.MemoLog:=Memo1;
 tcp.Tag := 0;
 tcp.Execute;
end;


 
vfb   (2006-05-26 13:24) [5]

Да, к слову
tcp := TSocks.Create(nil) стоит в функции изициализации библиотеки (вместе с созданием формы), а

procedure TfrmUsers.RequestComplete(Sender: TObject);
Begin
 can_close:=true;
//  tm.Enabled:=false;
end;


 
Сергей М. ©   (2006-05-26 14:27) [6]

Что показывает отладчик ?


 
vfb   (2006-05-26 18:13) [7]

На самом деле, он показывает, что Process is not accessible.
Вижу только Thread status - что три потока Runnable
И все три в ntdll.KiFastSystemCallRet

Правда, если честно, исторически сложилось, что я с gdb привык общаться. А тут для меня почти всё - темный лес.


 
Сергей М. ©   (2006-05-29 08:26) [8]


> vfb   (26.05.06 18:13) [7]


Про отладочные точки останова хоть что-нибудь слышал ?



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

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

Наверх





Память: 0.47 MB
Время: 0.039 c
2-1159717369
Footballer
2006-10-01 19:42
2006.10.22
Трафик


2-1159904904
Lelja
2006-10-03 23:48
2006.10.22
размещение справки в проге


8-1143042841
Sco
2006-03-22 18:54
2006.10.22
Отразить обьект


2-1160235614
Iamdanil
2006-10-07 19:40
2006.10.22
Определить имя компьютера по имени сетевой папки


2-1159791731
svt
2006-10-02 16:22
2006.10.22
Мастера, подскажите как сделать так, чтобы правильно





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский