I am using TIdTCPClient and TIdTCPServer components of Indy Sockets for sending and receiving messages between objects of a class called Agent.Each Agent is responsible for doing a particular task and starts execution after receiving the message. I know that TIdTCPServer opens a thread when a message is received and OnExecute Event is executed on this additional thread. In fact my final goal is to do a parallel computation, so I am handling a series of heavy calculations in OnExecute Event. Is this approach for multi-thread programming and parallel computation a good one? Can we use the additional thread of Indy Sockets which is opened for receiving messages for a heavy computation? if not, what is the alternative? For example can I use TThreadobjects to handle this parallel computation?
Related
I am making a client program in Delphi 7 with Indy 10.
It must connect to the server with TIdTCPClient and keep alive the connection for sending and getting commands and replies until the program is closed.
The server can maintain only one constant connection per client to send info-messages.
TIdTCPClient is listening through a reading thread.
QUESTION:
I am sending a request to the server (using WriteLn) from some procedure to get a list of strings, for example. How can I get the answer (reply) for that request in the same procedure, without leaving it? Like using TIdHTTP.
I see 2 solutions:
making the request from one procedure and handle it in other - the code and logic will be more complicated.
for each request in a procedure, create a new TIdTCPClient (Connect, WriteLn, ReadLn, Disconnect, Free) and handle request. But I do not like this solution as it causes large overhead.
Since a reading thread is involved, it does complicate things a little. The reading thread needs to be the one to receive all of the replies and then it can dispatch them to handlers as needed.
Your first solution is fine, if you don't mind breaking up your code. This is the simplest solution, and the best one if the main thread is the one making the requests. You should never block the main thread.
As you mentioned, your second solution is not a very good one.
Another solution would be to create a TEvent for each request, and put each request into a list/queue somewhere. Have the reading thread find and signal the appropriate event when a response is received. The sending procedure can then wait on the event until it is signaled (TThread.Synchronize() works this way, for example). If the procedure is running in the main thread, use MsgWaitForMultipleObjects() to do the wait, so you can still service the main message queue while waiting.
I use c++ builder XE8, and I am a beginner. I want to use OnReceive and OnSend event of Indy server and client to make it work in non-blocking mode. I have read that Indy server/client works in blocking mode, and to make it work i have to use a separate thread. I also found example but those were in delphi not c++. Can I do this using Intercept/IOHandler, or I have to use separate thread ? Please give a short example code.
I want to use OnReceive and OnSend event of Indy server and client to make it work in non-blocking mode.
Indy uses blocking sockets exclusively. You cannot use them in a non-blocking mode. There are no OnReceive and OnSend events, like there are in the VCL's TClientSocket and TServerSocket components.
I have read that Indy server/client works in blocking mode, and to make it work i have to use a separate thread.
That is true.
Indy servers are multi-threaded. TIdTCPServer has OnConnect, OnDisconnect, and OnExecute events that are triggered in the context of worker threads, one for each connected client. TIdUDPServer has an OnUDPRead event that is triggered in the context of worker threads, one foor each listening port. You need to do your socket I/O in these events. Typically, you would simply perform whatever read/write operations you need and let Indy block the calling thread as needed.
Indy clients are mostly single-threaded, they run in the context of whatever thread they are used in (TIdCmdTCPServer and TIdTelnet being the exception to that rule). So you usually have to create your own thread to manage the socket I/O if you want non-blocking behavior.
Please read the documentation for more details:
Introduction to Indy
I also found example but those were in delphi not c++.
And? The components are the same in both languages. So either translate the code from Pascal to C++, or just use the code as-is (did you know that you can use Delphi code in C++Builder projects? You can).
Can I do this using Intercept/IOHandler
No. An Intercept is meant for manipulating data as it passes to/from the connection (to apply encryption, compression, etc). The IOHandler performs the actual I/O operations, but it has nothing to do with threading.
or I have to use separate thread ?
Yes.
Please give a short example code.
There are plenty of examples readily available if you search around. StackOverflow is not the place to ask for them.
I am connecting to a server as a client using TCPSocket. The main point is to keep connection open and send there or receive from there messages as soon as they arrive.
There are no problems with sending messages, but doing socket.recv(n) in main thread when server has nothing to respond with, makes client's main thread to pause while waiting for data.
What is the good practice to work with persistent connections in Ruby to prevent main thread blocking?
Let's suppose that extra thread should be used. Where to insert this thread initialization in Rails app? Make a worker process?
Receiving data on a dedicated thread is certainly possible. But also consider using IO#select or IO#read_nonblock. (TCPSocket is a subclass of IO.) If you are waiting for data to come from any one of several sockets, IO#select would be ideal. If you are doing some other processing on the main thread, but also need to remain responsive to input coming in from a socket, you can call IO#read_nonblock at intervals.
When receiving data from a indy TCPServers execute method i generally handle it by reading the data by doing the following:
AContext.Connection.IOHandler.ReadLn;
and then process the data in the execute method. Most of the data that comes through are small JSon strings.
In the future i will need to handle larger data chunks and was wondering what the best pratice is to do so?
Is it a good idea to add the incoming data to a TidContext class and process it using some worker thread? Any thoughts or code samples would be appreciated. I use Indy 10 and Delphi XE3
The OnExecute event is already triggered in a worker thread, so it doesn't matter how long it takes to receive the data. As long at the data only has 1 (CR)LF at the end of it, ReadLn() will not care how long the string actually is (subject to the IOHandler's MaxLineAction and MaxLineLength properties, which you can tweak if needed). However, if the data has more than 1 (CR)LF in it, then you will have to either:
transmit the string length before transmitting the actual string, then use ReadLongInt() and ReadString() instead of ReadLn() in the receiving code.
terminate the string with a different delimiter than (CR)LF at the end, and then pass that delimiter to ReadLn() so it knows when to stop reading.
If the server has to receive incoming requests at a guaranteed rate, without blocking the consumers by slow request processing, saving the big data chunks to a datastore (file, database) for later processing could be a solution.
This would make the HTTP server thread available for the next request as soon as possible.
It also allows to do the data processing by multiple worker servers, with load balancing.
I am writing an app that sends e-mail messages using Indy.
Every message is sent by a thread.
Currently I am connecting to TidSMTP inside the thread, so for sending 10 mails, I need 10 threads and I connect 10 times.
Is it safe (which are the drawbacks?) of having a single TidSMTP (outside of the thread), call Connect once and then call TidSMTP.Send inside the thread?
Will TidSMTP manage thing correctly?
Note: the idea is to avoid to connect every time (if possible), in case of many emails to be sent it could be an advantage. (does it makes sense to get worried for this, or calling Connect in every thread is pefectly ok?).
Why don't you use only 1 thead in which you have a TIdSMTP and a TList in which you store TIdMessage's and after each send you free the TIdMessage from the list, in this case you avoid overhead and keep it simple.
What if you want to send 200 e-mails, well if you start 200 threads then your application will use over 200 Mb only for those 200 threads not to mention that there can be problems starting that many threads in your application.
Bottom line add a TList in which you temporarily store prepared TIdMessages and inside the thread a while loop that will check if the list has any messages to send, if it has then grab, send and remove from list.
Technically, you can call Connect() in one thread and then call Send() in other threads. However, you would have to serialize access to Send(), otherwise the sending threads can overlap each other and corrupt the SMTP communication. Dorin's suggestion to move all of the SMTP traffic to a single thread with a queue is the best choice. However, the queue itself needs to be accessed in a thread-safe manner, so using a plain TList or TQueue by itself it not good enough. Either use TThreadList (or Indy's own TIdThreadSafeList) instead of TList, or wrap the TQueue with a separate TCriticalSection.