This shows you the differences between two versions of the page.
— |
public:howto:onstatus [2007/11/30 14:30] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== A Guideline For The OnStatus Callback. ====== | ||
+ | Synapse can do callbacks at several tactical places. This way you can trace opening or closing of the socket, log errors, or count the amount of data transferred. | ||
+ | |||
+ | This all happens in one callback handler. | ||
+ | |||
+ | Assigning the callback handler is relatively easy. First, you will have to define a callback procedure, we will talk about that later. | ||
+ | |||
+ | Then you assign the callback to a TBlockSocket descendant. Protocol implementations all have their sock property public or published. | ||
+ | |||
+ | like this: | ||
+ | |||
+ | <code delphi> | ||
+ | sock := TTCPBlockSocket.Create; | ||
+ | sock.OnStatus := SockCallBack; | ||
+ | </code> | ||
+ | |||
+ | or | ||
+ | |||
+ | <code delphi> | ||
+ | HTTP := THTTPSend.Create; | ||
+ | HTTP.Sock.OnStatus := SockCallBack; | ||
+ | </code> | ||
+ | |||
+ | This is the definition of the callback function: | ||
+ | |||
+ | <code delphi> | ||
+ | THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason; | ||
+ | const Value: string) of object; | ||
+ | </code> | ||
+ | |||
+ | Define SockCallBack? as follow: | ||
+ | |||
+ | <code delphi> | ||
+ | TMyObject = class (TObject) | ||
+ | //..your other declarations | ||
+ | procedure SockCallBack (Sender: TObject; Reason: THookSocketReason; const Value: string); | ||
+ | end; | ||
+ | </code> | ||
+ | |||
+ | ! Please note: Value is declared as string, but mostly contains an integer value. You can use StrToIntDef(Value, -1) to retrieve the value. | ||
+ | |||
+ | THookSocketReason is defined as follows: | ||
+ | |||
+ | <code delphi> | ||
+ | THookSocketReason = ( | ||
+ | HR_ResolvingBegin, | ||
+ | HR_ResolvingEnd, | ||
+ | HR_SocketCreate, | ||
+ | HR_SocketClose, | ||
+ | HR_Bind, | ||
+ | HR_Connect, | ||
+ | HR_CanRead, | ||
+ | HR_CanWrite, | ||
+ | HR_Listen, | ||
+ | HR_Accept, | ||
+ | HR_ReadCount, | ||
+ | HR_WriteCount, | ||
+ | HR_Wait, | ||
+ | HR_Error | ||
+ | ); | ||
+ | </code> | ||
+ | |||
+ | Based on the value, you know what the event is. | ||
+ | |||
+ | :!: Note: Some protocols like FTP using more then jist one socket. Be sure that you are monitoring right socket. For example, if you wish to monitor FTP data stransfers, hook TFtpSend.DSock.Onstatus. | ||
+ | |||
+ | How To Put An Callback With An Abstract Object? | ||
+ | |||
+ | For some applications, like a quick-and-dirty non-oops console application, you can define an abstract object with a class function attached and use it as callback handler. | ||
+ | |||
+ | This application (a plugin for the gpu distributed computing over a p2p network project) uses this technique, code below is extracted from this application: | ||
+ | http://cvs.sourceforge.net/viewcvs.py/gpu/gpu_solar/src/dllbuilding/earthsim/earthsim.dpr?rev=1.1.1.1&view=markup | ||
+ | |||
+ | |||
+ | <code delphi> | ||
+ | uses ..., typinfo; | ||
+ | |||
+ | //declaration of a class with one class method: | ||
+ | |||
+ | type callback = class | ||
+ | class procedure Status (Sender: TObject; Reason: THookSocketReason; const Value: String); | ||
+ | end; | ||
+ | |||
+ | //implementation | ||
+ | |||
+ | class procedure callback.Status(Sender: TObject; Reason: THookSocketReason; | ||
+ | const Value: String); | ||
+ | var v: String; | ||
+ | begin | ||
+ | if (reason=hr_readcount) or | ||
+ | (reason=hr_writecount) or | ||
+ | (reason=hr_canread) then | ||
+ | exit; | ||
+ | v := getEnumName (typeinfo(THookSocketReason), integer(Reason)) + ' ' + Value; | ||
+ | writeln (v); | ||
+ | end; | ||
+ | </code> | ||
+ | |||
+ | attaching this callback to a socket: | ||
+ | |||
+ | <code delphi> | ||
+ | Sock := T[UDP/TCP/..]BlockSocket.Create; | ||
+ | Sock.OnStatus := callback.Status; | ||
+ | </code> | ||
+ | |||
+ | Hope this helps you out. |