Indy TCP Server Freezes, no idea why - delphi

I have a Server and a client (Delphi).
The client gets login details and then connects to the server sends them to the server to be validated, the server receives the data validates it then returns whether the given data is correct.
If the data was correct the client continues to the next window where they enter some data into corresponding fields and then sends the data to the server, when the server receives the data it stores it and then replies to the client that it stored it successfully. When the client has been notified that the data was stored successfully it displays a message notifying the user and then terminates.
While testing this, with the client running on four different computers, (Each computer would have opened and closed the client about 6 times) the server suddenly stops replying to the clients (Clients display message saying "Connection closed gracefully")
This is the error the server is returning:
So the error appears to be when ADOQuery opens the connection to execute the SQL, why would it cause a exception only after 30 executes?
Any Suggestions to what my problem is as I have no idea what it might be.
Thanks for your help :)

If a client receives a "Connection closed gracefully" error, it means the server closed that client's connection on the server side. If your server code is not explicitly doing that, then it usually means an uncaught exception was raised in one of the server's event handlers, which would cause the server to close the socket (if the exception is raised after the OnConnect event and before the OnDisconnect event, OnDisconnect is triggered before the socket is closed). TIdTCPServer has an OnException event to report that condition.
TIdTCPClient closes the socket during destruction if it is still open.
Update: TIdTCPServer is a multi-threaded component. Each client connection runs in its own thread. ADO uses apartment-threaded COM objects that are tied to the thread that creates them, and can only be used within that thread context unless marshaled across thread boundaries using CoMarshalInterThreadInterfaceInStream() + CoGetInterfaceAndReleaseStream(), or the IGlobalInterfaceTable interface.
In this situation, you should either:
give each client its own ADO connection and query objects. You could either:
A. create them in the OnConnect event and store them within the TIdContext for use in the OnExecute event, and then free them in the OnDisconnect eventt. Or just create and free them in the OnExecute event on an as-needed basis.
B. derive a new class from TIdThreadWithTask and override its virtual BeforeExecute() and AfterExecute() methods to create and free the ADO objects, and then assign one of the TIdSchedulerOfThread... components to the TIdTCPServer.Scheduler property and assign your thread class to the TIdSchedulerOfThread.ThreadClass property. Then, in the server events, you can use TMyThreadClass(TIdYarnOfThread(TIdContext.Yarn).Thread) to access the calling thread's ADO objects.
Create a separate pool of ADO objects. When a client needs to access the database, have it marshal the appropriate ADO objects to the calling thread's context, and then put the objects back in the pool when finished.
Either way, since ADO is COM-based, don't forget to call CoInitialize/Ex() and CoUnintialize() for each client thread that needs to access ADO objects, either in the OnConnect and OnDisconnect events, or in the TIdThreadWithTask.BeforeExecute() and TIdThreadWithTask.AfterExecute() methods.

Related

Is there a way to have my response sent immediately in the TIdHTTPServer.OnCommandGet event?

I have some tasks to do for certain commands I receive and would like to keep the client from (read-)timeouts by sending some data while doing the task.
Does the AResponseInfo object offer anything to accomplish this?
I currently use the ContentText property, but it sends the data (as it seems) at the end of the event handler.
By default, TIdHTTPServer sends a response when the OnCommand... event handler exits. However, it is possible to send a response sooner, by either:
calling the AResponseInfo.WriteHeader() and AResponseInfo.WriteContent() methods after populating the AResponseInfo properties as needed.
writing directly to the TCP socket, and then setting the AResponseInfo.HeaderHasBeenWritten property to true so TIdHTTPServer does not try to send its own response.
Note: once you send a response to the client, the client is free to send new requests using the same TCP connection (if HTTP keep-alives are used), but you will be holding up the connection from processing those requests until you exit the OnCommand... event handler.
If you have long processing to do, it is generally better to send a normal response back to the client as soon as possible, for instance with a 102 Processing response, exit the OnCommand... event handler so the server regains control of the connection, do the actual processing in the background, and let the client query the status of the processing using subsequent requests as needed. You could assign a cookie or other type of server-generated ID to the processing, and then have the client send that cookie/ID back to the server to query the processing's status.

How to reverse connection initiator in IdTCPClient and IdTCPServer having the same functionality?

I would like to create Inter Machine Communication using INDY TCP Client and Server components. IdTCPServer has an event called OnExecute which is triggered when client wants something from server. I would like to create the same functionality, when SERVER sends request to the CLIENT which would have the same OnExecute event, just like it was working as server. Is it easily to achieve? I need it because I can connect to the peer only one-way (NAT)
IdTCPServer has an event called OnExecute which is triggered when client wants something from server.
That is not how the TIdTCPServer.OnExecute event works. It is called in a continuous loop for the lifetime of the connection, regardless of anything that the client or server do with the connection between the time it is connected and the time it is disconnected.
The typical usage of the event is to block the calling thread waiting for the client to send a packet, then reply with a packet, and then exit, letting the loop fire the event again so it can wait for the next client packet.
But this is not the only way the event can be used.
I would like to create the same functionality, when SERVER sends request to the CLIENT which would have the same OnExecute event, just like it was working as server. Is it easily to achieve?
TIdTCPClient does not implement that kind of logic natively. It merely provides a connection, but you have to write your own code to tell it when to read and write data over that connection.
For what you are asking, you will need to create your own worker thread, either by writing a TThread/TIdThread-derived class, or using the TIdThreadComponent component. When the client connects to the server, start the thread. When the client disconnects, stop the thread. Then your thread can do whatever you want with the connection, just like with the TIdTCPServer.OnExecute event.
Depending on the format of your commands/responses, you might be able to use TIdCmdTCPClient instead of TIdTCPClient. TIdCmdTCPClient runs its own thread internally, and its CommandHandlers collection parses inbound requests and generates outgoing responses. All you would have to do is populate the collection with TIdCommandHandler objects that define the parsing criteria for each request, and assign an OnCommand event handler to each one to react to each request that the server sends.

Lifecycle of MQ Connection in JSF - Connection Closed

I use JSF 2 an WebSphere MQ for Messaging (JMS).
I want to know what's the best practice to open / close the QueueConnection?
Should I use for each client session one connection and open it on (post-)construction and close it on (pre-) destruction like here?
Or are there better ways to handle the connection? E.g. "Open EntityManager in View" Pattern for JDBC/JPA?
Avoid creating a new connection for each getMessage() invocation. Create one connection at construct time, save it as an instance variable.
For each getMessage() call, create a new session, get the message, then close the session.
When you're done, close the connection at destruction time.

Aborting ISAPI request from client:

App Chain:
Running a Delphi ISAPI application under IIS 7.5/Server 2008R2 - 32 bit mode and Classic Mode pipeline.
ISAPI app (TISAPIApplication) is built with Delphi XE.
Client is a Delphi exe that generates an XML doc containing request content, including unique internal identifier generated on client side for tracking the request content, etc.
Client spawns a thread and hits the ISAPI app on webServer, passing in XML doc containing request info;
Client thread waits on server reponse and signals client when thread terminates, indicating request has been processed on server.
Problem:
User mistakenly sends a request that has potential to run for hours and/or choke up our infrastructure.
I want to enable the client app to send a message to server to abort that request (ONLY that request).
Proposed Solution:
My proposed solution is to create a dictionary on the webServer associating my client side unique identifier with a particular handle or ID for the thread that is generated on server side by the ISAPI process to handle the request. This server side ID could subsequently be used to track and abort the request if necessary when client sends request to abort, using the client side identifier.
BUT - I don't know what property/Thread-ID/handle I should be grabbing on the server side, how get to it, and how to use it to abort the request. If I can access the request handler as a Delphi thread all this should be easy enough.
Anyone know how to go about this? I'm quite certain this can be done, but I don't know exactly how to do it. Have looked around in the Delphi XE docs on TWebRequest etc, haven't found much yet.
Again, please note: I need to kill ONLY that particular request and not the whole ISAPI process - I don't want to abort any other pending requests.
From one of my mentors:
Best way to do this is to spawn a new thread in the ISAPI generated thread and store its reference in a session cache. ISAPI thread waits on this thread while it does your work - you can terminate this thread via your cached reference and ISAPI thread will terminate.
I implemented this solution and it works very well.

Transferring Data Directly between 2 Connections in Indy (TIdContext)

ive a sever running TIdTCPServer, and Client Using Web Browser (or any other software) to Communicate, i dunno the protocol, but what im trying to do is to Send The Data between the client and another Connection (Both Connected to the same TIdTCPServer) for example the data sent by the first client is transmitted to the second client, and the data sent by the second client is transmitted to the first client, like a proxy (i cant really use a proxy server since its just this one condition) and the TIdTCPServer should still be receiving other clients and processing their data.
i stumbled upon the first line of code, since TIdContext.Connection.Socket.ReadLn requires a Delimiter, and the Client's Protocol is unknown to the server.
any ideas?
thanks.
You can look at the source code for TIdMappedPortTCP and TIdHTTPProxyServer to see how they pass arbitrary data between connections in both directions. Both components use TIdSocketList.SelectReadList() to detect when either connection has data to read. TIdMappedPortTCP then uses TIdBuffer.ExtractToBytes() and TIdIOHandler.Write(TIdBytes), whereas TIdHTTPProxyServer uses TIdTCPStream and TIdBuffer.ExtractToStream() instead.

Resources