Difference between revisions of "TWSocket.OnDataAvailable"
Transformer (talk | contribs) |
|||
(6 intermediate revisions by one other user not shown) | |||
Line 7: | Line 7: | ||
== Description == | == Description == | ||
− | '''OnDataAvailable''' is | + | '''OnDataAvailable''' is triggered every time a packet has been received on the interface the corresponding socket is attached (bound) to. In this event you should fetch the received data via [[TWSocket.Receive|Receive]], otherwise the event will occur forever. As long as there is still data in the receive buffer of the socket the event will be raised again. |
e.g. | e.g. | ||
Line 18: | Line 18: | ||
== Example == | == Example == | ||
+ | |||
+ | With following definition: | ||
+ | '''const''' EndOfLine = #13#10; | ||
+ | |||
+ | and on the MyForm | ||
+ | ... | ||
+ | WSocket :TWSocket; | ||
+ | ... | ||
+ | Terminal :TMemo; | ||
+ | ... | ||
+ | |||
+ | append the received line to the Memo by using '''[[TWSocket.ReceiveStr | ReceiveStr]]''': | ||
+ | '''procedure''' TFormMyForm.WSocket1'''DataAvailable'''(Sender: TObject; ErrCode: Word); | ||
+ | var Line :string; | ||
+ | begin | ||
+ | if ErrCode <> 0 then Exit; | ||
+ | |||
+ | with Sender as TWSocket do begin | ||
+ | Line := '''ReceiveStr'''; | ||
+ | Line := LeftStr(Line,Length(Line)-Length(EndOfLine)); // remove EndOfLine | ||
+ | Terminal.Lines.Add('Line: '+ IntToStr(Length(Line)) +' '+Line); | ||
+ | end; | ||
+ | end; | ||
+ | |||
+ | ... or by using '''[[TWSocket.Receive | Receive]]''': | ||
+ | '''procedure''' TFormMyForm.WSocket1'''DataAvailable'''(Sender: TObject; ErrCode: Word); | ||
+ | '''var ''' Count :integer; | ||
+ | Buffer :array [0..255] of char; | ||
+ | Line :string; | ||
+ | '''begin''' | ||
+ | if ErrCode <> 0 then Exit; | ||
+ | |||
+ | with Sender as TWSocket do | ||
+ | Count := '''Receive'''(@Buffer, Sizeof(Buffer)-1); | ||
+ | |||
+ | if Count <= 0 then Exit; | ||
+ | |||
+ | // Assume the Buffer was long enough and the whole line ist in the Buffer. | ||
+ | Buffer[Count-Length(EndOfLine)] := #0; // "delete" LineEnd | ||
+ | // zero terminiated String | ||
+ | Line := Buffer; // copy to string | ||
+ | if Length(Line) = 0 then Exit; | ||
+ | Terminal.Lines.Add('Line: '+ IntToStr(Length(Line)) +' '+Line); | ||
+ | '''end;''' | ||
+ | |||
+ | If 'Hello World!' was received, you will see: | ||
+ | Line: 12 Hello World! | ||
== Best practices == | == Best practices == |
Latest revision as of 06:42, 9 July 2011
Main page -> ICS component reference -> TWSocket -> OnDataAvailable
Definition
event OnDataAvailable Sender:TObject; ErrCode:Integer;
Description
OnDataAvailable is triggered every time a packet has been received on the interface the corresponding socket is attached (bound) to. In this event you should fetch the received data via Receive, otherwise the event will occur forever. As long as there is still data in the receive buffer of the socket the event will be raised again.
e.g.
- There were 512 bytes in the buffer
- you only feteched 256 bytes of them at the first time
- the OnDataAvailable will occur a second time, since 256 bytes are left
- if you fetch the other 256 bytes OnDataAvailable stays quiet until the next packet is received
If your program is in the eventhandler now it won't fire again until all the code in the handler has been run, so it may be wise to put long running processing (e.g. database queries) into a worker thread you create in the eventhandler or pass the data to a buffer which is on the other end processed by a thread (so the buffer contents is the thread's workload).
Example
With following definition:
const EndOfLine = #13#10;
and on the MyForm
... WSocket :TWSocket; ... Terminal :TMemo; ...
append the received line to the Memo by using ReceiveStr:
procedure TFormMyForm.WSocket1DataAvailable(Sender: TObject; ErrCode: Word); var Line :string; begin if ErrCode <> 0 then Exit; with Sender as TWSocket do begin Line := ReceiveStr; Line := LeftStr(Line,Length(Line)-Length(EndOfLine)); // remove EndOfLine Terminal.Lines.Add('Line: '+ IntToStr(Length(Line)) +' '+Line); end; end;
... or by using Receive:
procedure TFormMyForm.WSocket1DataAvailable(Sender: TObject; ErrCode: Word); var Count :integer; Buffer :array [0..255] of char; Line :string; begin if ErrCode <> 0 then Exit; with Sender as TWSocket do Count := Receive(@Buffer, Sizeof(Buffer)-1); if Count <= 0 then Exit; // Assume the Buffer was long enough and the whole line ist in the Buffer. Buffer[Count-Length(EndOfLine)] := #0; // "delete" LineEnd // zero terminiated String Line := Buffer; // copy to string if Length(Line) = 0 then Exit; Terminal.Lines.Add('Line: '+ IntToStr(Length(Line)) +' '+Line); end;
If 'Hello World!' was received, you will see:
Line: 12 Hello World!
Best practices
- do not call Application.Processmessages or any other form of a message pump (such as TWSocket's message pump or GetMessage or any modal form) within the event, otherwise you can run into severe reetrancy problems.