Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Server "connection" object/variable when disconnecting from server side
(10-30-2020, 09:28 AM)noname007 Wrote: 1. Apart from the port exaustion problem, if the client disconnects the operation is at least 10 times faster than if the server disconnects, in any scenario from below. But because of the port exhaustion, the client never disconnects in my application, it never performs a disconnection, only asks for it.

There should be no effect on server-side performance whether the server or the client performs the disconnect first. A disconnect is a disconnect, and the server checks for that condition in between each firing of the OnExecute event.

If anything, the only performance hit on the client disconnecting first is the port exhaustion issue due to the client entering the TIME_WAIT state and potentially not being able to reconnect to the server right away.

(10-30-2020, 09:28 AM)noname007 Wrote: 2. If the server blindly disconnects, in most scenarios this is 4-10 times slower than if the server waits for the client to ask for the disconnection form the server (scenario no 3), which means this no 2 scenario is about 100 times slower than the scenario no 1.

The only way that makes sense to me is if the client is not paying attention to the disconnect and doesn't notice for awhile that the connection was closed. That should not be slowing down the server side.

(10-30-2020, 09:28 AM)noname007 Wrote: Plus this is prone to more exceptions, as the disconnect request may interrupt the data transmission

Not if the server is performing the disconnect in between transmissions, ie after sending its response and before reading a new request.

[quote="noname007" pid="7126" dateline="1604050109"]
and when I read it (ReadBytes) it may tell in many ways that the connection is no longer available.

Not really. It only has 1 way - it raises an exception. There may be different error codes behind that exception, depending on the particular condition that was detected due to thread timing. But you shouldn't care about that. If you get a socket error, the connection is no longer in a stable state, so the only sane thing to do is close it.

(10-30-2020, 09:28 AM)noname007 Wrote: If the server and the client are on the same machine (or even part of the same application), a single client thread can run at most 3 requests per second (using an Intel 4.4 hz processor, 16 gb of RAM).

You should be getting a LOT more bandwidth than that. Unless you are taxing the CPU too much and starving threads for time.

(10-30-2020, 09:28 AM)noname007 Wrote: In order to speed things up by an order of magnitude, I have to send a different request for the server (in which the client asks for disconnection), subsequent to the first request for data; after receiving it, the server disconnects without replying in any way.

If it is faster for the server to wait for a 2nd request before closing the connection, than it is to just close the connection after sending the 1st response, there there is something very funky in your setup that you are not accounting for correctly. What you are describing is not what should be happening.

(10-30-2020, 09:28 AM)noname007 Wrote: So this is the fastest and most reliable I have found until now is: client connects, client sends data request, client receives data request, client sends disconnect request, server performs the actual disconnection.

That should neither be the fastest nor the safest/reliable way to go.

(10-30-2020, 09:28 AM)noname007 Wrote: In my model, the client does not disconnect, it never performs the disconnection. Only the servers perform the disconnectinons. The client only requests from the server "disconnect this connection", and the server does it without sending any reply to the client.

That does not preclude the possibility of the network itself dropping a connection unexpectedly. Networks are not perfect, things happen outside of an application's control. You need to be resilient to that. So your server needs to be prepared to handle the OnDisconnect event before a client explicitly requests a disconnect. And yes, the client must still perform a disconnect on its side, even if it performs that after the server performs its disconnect. Both parties need to cleanup after themselves.

(10-30-2020, 09:28 AM)noname007 Wrote: Anyway, the requests are processed very quickly, so the server has no time to notice a broken connection.

Nonetheless, the race condition still exists. The connection CAN drop before (or even while) the server is sending a response.

(10-30-2020, 09:28 AM)noname007 Wrote: This is interesting, because what I see is this: a connection variable I pick from the OnExecute event and store in the queue list along with a tag and the peer coordinates, when retrieved milliseconds later no longer has the same attributes (it may point to a different ip and port, or be invalid).

Then you clearly have undefined behavior in your code. What you describe can happen if you are trying to access an object after it been destroyed, for instance. You need to build in some better safeguards into your code to avoid that.

For example, if you insist on storing the Connection objects directly in your queue, you will have to put a thread-safe lock on the queue, or even the individual requests themselves. When the OnDisconnect event fires, lock the queue, remove/invalidate any requests that refer to that Connection, and unlock the queue. When sending a response, lock the queue, send the response only if the Connection is still invalid, and then unlock the queue.

This is why I don't recommend storing the Connection objects themselves in your queue.

(10-30-2020, 09:28 AM)noname007 Wrote: I could not find any error in my code, and the connection variable is untouched.

Your variable, perhaps, but not the object the variable is pointing at.

(10-30-2020, 09:28 AM)noname007 Wrote: This may be slow as I will be locking the list a lot of times searching for a particular connection.

Yes, but it is safer. Since TIdTCPServer is a multi-threaded component, you have to take thread safety into account, especially since you don't own the threads or the Connection objects. Since you are doing asynchronous processing outside of the OnExecute event, extra measures have to be taken.

One thing you could do to speed up the searches is assign each client a unique ID, and store the Connection object in a thread-safe dictionary/hashtable keyed by that ID, and then store only the ID in the queue. In the OnDisconnect event, you can lock the table, remove the ID, and unlock the table. When sending a response, lock the table, lookup the ID and if found then send the response, and unlock the table.

You are still doing a fair amount of locking/unlocking, especially since you have such short-lived connections, but at least the storage/retrieval operations will be performed using fast hash lookups rather than linear searches. And there are ways to mitigate the overhead of locks, such as using a spin-lock rather than a criticalsection/mutex, for instance (if you are careful with them).

(10-30-2020, 09:28 AM)noname007 Wrote: I also had the same problem of inconsistence using /storing the Context object itself

Then you likely have an underlying logic flaw in your code, where it is not adequately protecting its objects from concurrent access across multiple threads correctly.


Messages In This Thread
RE: Server "connection" object/variable when disconnecting from server side - by rlebeau - 10-30-2020, 05:36 PM

Forum Jump:

Users browsing this thread: 1 Guest(s)