Hello, while looking through the classes in fcl-net's ssockets unit, I noticed that the server class provides a method to enable non-blocking mode, however the client class TINetSocket does not. I am not sure why this was not included, as having a non-blocking client socket can be very useful when working with custom protocols where either the client or the remote server can initiate a message at any time. A very useful use of a non-blocking TCP socket on the client-side is to use it within a thread where you have s.Read(buf,1024) in a loop to constantly check for data from the server-side and act upon it in near real-time. An example event loop within a thread in a GUI application might look like this:
While running do
begin
l:=s.Read(buf,1024);
if l > 0 then processData(buf);
if Length(sendBuf) > 0 then sendBuffer;
end;
The sendBuf can be written to from outside of the thread using locks to allow other parts of the application to queue data out to the socket. A better solution is to use select, poll, or epoll in a proper event loop. However, I have yet to figure out how to implement a proper select event loop for sockets in FreePascal/Lazarus. I can see the fpAsync unit, but I am unable to see any examples on it's use. This example above will take much more CPU than a proper select event loop.
It is possible to use non-blocking with a client socket by using this code here: FpFcntl(s.Handle, F_SetFl, O_NONBLOCK);
In this example, s is a class instance of TInetSocket. This works and enables the client-side socket in non-blocking mode. When no data is available from the socket s.Read happily returns -1 as expected. It seems that fpSock provides access to this ability, but it is not well documented or I am just unable to locate the documentation for it. It also seems that fpSock/fpAsync might be UNIX/Linux only, although both OS X and Windows also provide a select/poll like API for sockets as well.
I guess my other option to this would be to have the server constantly send a ping packet to each connected client so the s.Read returns and the thread code can continue processing and sending any data out to the server. I guess I am just more used to event-based network programming where blocking sockets don't exist.
Does the Synapse Lazarus components both offer RAW TCP connections, and the ability to attach events such as connected, disconnected, dataWaiting, etc... ?