Delphi ScktComp: When is the onWrite event being fired? - delphi

I have come to the point of thinking that the onWrite Event of a ClientSocket is redundant when I directly write bytes into the socket connection via SendBuf().
Is my point of thinking somewhere in the desert?
The Delphi Documentation is also somewhat bad because it just sais: "Write a routine for the onWrite event to write into the socket connection."

OnWrite is used when you're using asynchronous IO (when you have ClientType = ctNonBlocking, in other words). It's called when the socket's ready for you to send data.
Thus, your thinking's only half in the desert: if you're using ctBlocking, then don't bother with OnWrite at all. If you need that thread to send data and get on with other stuff at the same time, then use ctNonBlocking and write to the socket in OnWrite.
When you use async sockets, Windows will send your socket a CM_SOCKETMESSAGE, handled by TCustomWinSocket.CMSocketMessage. When that message has its SelectEvent property set to FD_WRITE, the OnWrite's (ultimately) invoked.
The magic ingredient here is the call to WSAAsyncSelect in TCustomWinSocket.DoSetAsyncStyles.

Related

TinyOs nesc Packet acknowledge

I want to write a mote-mote radio communication program, and want the receiver acknowledges back to the sender. I know the PacketAcknowledgements is recommended, but there are some questions I'm not sure about this interface.
1. If I use it in the sender mote,should i also uses interface Receive in the module of the sender mote
2. Should I write extra code in the receiver mote? Should I use interface PacketAcknowledgements too?
3. command error_t requestAck(message_t *msg) and command bool wasAcked(message_t *msg) should be used when and where
No.
No.
You need to call requestAck on a packet you're about to send just before calling send from interface AMSend or Send. Be sure to check an error code returned by requestAck, because FAIL indicates that the communication layer doesn't support synchronous acknowledgements (it depends on the radio chip and driver you use). Once the packet is sent, i.e., inside event sendDone (or later), call wasAcked, which returns true if the packet was acknowledged by the receiver.
More info in:
https://github.com/tinyos/tinyos-main/blob/master/tos/interfaces/PacketAcknowledgements.nc

Sending messages to TApplication

I have an application that can send a message to another application. Under pre-Win8 systems, that works fine. You give it the class or title, it uses enumwindows and finds the target window. With Win8, you can only enumerate top level windows, which means the TApplication class. The sending side is happy with that, but the receiver isn't.
To catch the message I'm using this code within my target form ...
function Tmain.AppMsgHookFunc(var wmsg : TMessage) : Boolean;
begin
Result := False;
if wmsg.Msg = WM_COPYDATA then begin
// Post the caught message back to this form.
postmessage (handle,wmsg.Msg,wmsg.WParam,wmsg.LParam);
end;
end;
... and then activate this with application.hookmainwindow etc.
This never fires. I see that if I use sendmessage to send myself the message then it does fire, but if I use postmessage that doesn't work, even on XP. Any suggestions?
WM_COPYDATA is a sent message. The system marshals data cross-process. In order to do so, the system must know that the message has been processed in order to be able to tidy up the resources used to make the cross-process marshalling happen. And the way that the system knows that the message has been processed is by forcing you to send it synchronously. That means you must use SendMessage rather than PostMessage.
The documentation also contains this information, although you do need to know how to interpret it.
An application sends the WM_COPYDATA message to pass data to another application.
Note the use of the word "sends". That is code for the message being synchronous.
Raymond Chen discusses this issue here: Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?
The important difference from the standpoint of messages like
WM_COPY­DATA is that with sent messages, the window manager knows when
message processing is complete: When the window procedure returns. At
that time, it can free the temporary buffers used to marshal the
message from the sender to the recipient. If the message were posted,
the window manager would never be sure.
Suppose the message is placed in a MSG structure as the result of a
call to GetMessage. Now the window manager knows that the receiving
thread has the potential for taking action on the message and the
buffers need to be valid. But how would it know when the buffers can
be freed? "Well you can wait until the exact same parameters get
passed in a MSG structure to the Dispatch­Message function." But what
if the message loop discards the message? Or what if it decides to
dispatch it twice? Or what if it decides to smuggle it inside another
message?
Posted messages have no guarantee of delivery nor do they provide any
information as to when the message has been definitely processed, or
even if it has been processed at all. If the window manager let you
post a WM_COPY­DATA message, it would have to use its psychic powers
to know when the memory can be freed.

Read all data on Indy Server buffer

I have in TCP/IP a client that send a list of strings with writeln (all at the same time).
How can the TCPserver know that it has read all the data?
In Onexecute event, I have used:
If (not AThread.Terminated)and(athread.Connection.Connected) then
Memo1.lines.add(AThread.Connection.readln);
But the problem, is that some last lines are not read.
You should send each string with its own WriteLn(), then you can either:
Send the number of strings before sending the actual strings. The server can then read the number first, then call ReadLn() however many times the number says.
Send a unique terminating line after the strings. The server can then keep calling ReadLn() until the terminator is read. If you need to send a string that could be ambiquious with the terminator, escape the string before sending it, and then have the server unescape it after reading it.
Indy has reading/writing methods for handling both scenarios, such as WriteStrings(), ReadStrings(), WriteRFCStrings(), Capture(), etc.
On an unrelated note, you should not be checking the AThread.Terminated and AThread.Connection.Connected properties. Let Indy raise an exception if you try to read from or write to a disconnected socket, and let the server handle the exception. Also, TIdTCPServer is multi-threaded, and accessing UI controls in the OnExecute event (or OnConnect, OnDisconnect, or OnException) is not thread-safe. You MUST synchronize with the main UI thread to access them safely.

How to mix Sockets, Messages and Events

There is a thread that uses ADO Connection object, operates with a socket(s) and reacts on outer events using WaitForSigleObject or WaitforMultipleObjects. The thread has an endles loop with 3 actions:
While PeekMessage(MSG, 0, 0, PM_REMOVE) do ProcessMessages(MSG); //for processing messages of COM system
if Socket.CanRead then ... //CanRead is true when there is data in socket to read
if WaitForSingleObject(fHandle, 0) = WAIT_OBJECT_0 then ... //fHandle is handle of outer event
Almost all time the thread wastes CPU asking about all three types of events. Is there way to make thread to sleep until one of three types of events happend, like WaitForMultiplyObjects or GetMessage?
It is not clear what kind of library you use for network operations with socket. In general there are two possible ways to work with sockets, blocking or non-blocking sockets. If you use blocking sockets (Indy for example), then probably it is good idea to use separate thread for socket operations.
If you use non-blocking sockets (like ICS library), then you can use MsgWaitForMultipleObjectsEx function for synchronization with flags QS_ALLINPUT for all your input events. You can find more information on this function here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684245%28v=vs.85%29.aspx
Main difference of MsgWaitForMultipleObjectsEx from WaitforMultipleObjects is that first one can wake up not only when some object is signalated, but also when some specific or any message was posted in the queue. Seems it is what you asked.
For the record, ProcessMessages is the single most evil bit of code ever devised. It will create problems the like of which you simply can not imagine.
There are a number of non blocking socket components out there, so you do not have to poll for data FP's ICS comes to mind), perhaps you might want to try that to help with your socket problems.

Resetting comm event mask

I have been doing overlapped serial port communication in Delphi lately and there is one problem I'm not sure how to solve.
I communicate with a modem. I write a request frame (an AT command) to the modem's COM port and then wait for the modem to respond. The event mask of the port is set to EV_RXCHAR, so when I write a request, I call WaitCommEvent() and start waiting for data to appear in the input queue. When overlapped waiting for event finishes, I immediately start reading data from the queue and read all that the device sends at once:
1) write a request
2) call WaitCommEvent() and wait until waiting finishes
3) read all the data that the device sends (not only the data being in the input queue at that moment)
4) do something and then goto 1
Waiting for event finishes after first byte appears in the input queue. During my read operation, however, more bytes appear in the queue and each of them causes an internal event flag to be set. This means that when I read all the data from the queue and then call WaitCommEvent() for the second time, it will immediately return with EV_RXCHAR mask, even though there is no data to be read.
How should I handle reading and waiting for event to be sure that the event mask returned by WaitCommEvent() is always valid? Is it possible to reset the flags of the serial port so that when I read all data from the queue and call WaitCommEvent() after then, it will not return immediately with a mask that was valid before I read the data?
The only solution that comes to my mind is this:
1) write a request
2) call WaitCommEvent() and wait until waiting finishes
3) read all the data that the device sends (not only the data being in the input queue at that moment)
4) call WaitCommEvent() which should return true immediately at the same time resetting the event flag set internally
5) do something and goto 1
Is it a good idea or is it stupid? Of course I know that the modem almost always finishes its answers with CRLF characters so I could set the comm mask to EV_RXFLAG and wait for the #10 character to appear, but there are many other devices with which I communicate and they do not always send frame end characters.
Your help will be appreciated. Thanks in advance!
Mariusz.
Your solution does sound workable. I just use a state machine to handle the transitions.
(psuedocode)
ioState := ioIdle;
while (ioState <> ioFinished) and (not aborted) do
Case ioState of
ioIdle : if there is data to read then set state to ioMidFrame
ioMidframe : if data to read then read, if end of frame set to ioEndFrame
ioEndFrame : process the data and set to ioFinished
ioFinished : // don't do anything, for doc purposes only.
end;

Resources