Beijer Electronics (formerly QSI Corporation)

Manufacturer of Mobile Data and Human Machine Interface Terminals.
It is currently Fri Nov 24, 2017 6:15 am

All times are UTC - 7 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Wed Sep 10, 2014 7:54 am 
Offline

Joined: Fri Jan 31, 2014 7:28 am
Posts: 11
Terminal: G55

Is there a proper way to handle timeouts with HTTPClientV2? Currently we are using timers, but I believe this is causing issues.

The issue is that occasionally when a command is sent via HTTPClientV2, the G55 is immediately sending a FIN, ACK (verified via Wireshark). This means that any response doesn't get read even though a response is sent in a timely fashion (verified via Wireshark).

I will illustrate below the current implementation.

PoolTimer: Goes off every 500ms to send the next command in the queue
ResponseTimer: Goes off at 2s to indicate no response and to retry previous command

The ResponseTimer is being used for every command being sent by PoolTimer. This means that either the ResponseTimer is being reset to 2s every time or the ResponseTimer is continuing to tick down which causes premature closed connections. I believe scenario B is occurring and this is where the FIN, ACK is occurring as the timer is timing out from a previous command.

Looking at the library, I don't see any area where timeouts are handled. Is the above implementation a correct method of dealing with timeouts? Is there a better way to handle timeouts?


Top
 Profile  
 
PostPosted: Wed Sep 10, 2014 8:43 am 
Offline
QSI Support
QSI Support
User avatar

Joined: Wed Mar 08, 2006 12:25 pm
Posts: 881
Location: Salt Lake City, Utah
Can you post a Wireshark dump of the incorrect behavior? Specifically mention which Packet number exhibits the behavior you are not expecting.

Are you performing a POST or a GET?

I don't see any code in the HttpClientV2 object to actively close the connection until it has been closed by the other side. In other words, the HttpClientV2 object should send a Fin as soon as it receives a Fin from the server. (Note that HttpClientV2 supports HTTP 1.0, not 1.1, so keepalive is not supported).

Timeouts are handled strictly as part of the TCP stack (and are expressed in the form of a MSG_COMM_ERROR), and as such would usually be measured in minutes. As a general rule, I recommend against manually handling timeouts in the case of TCP connections as they tend to cause all sorts of crazy state issues.

Instead, you might want to handle the ConnectionClosed and EthernetError events to put your object back in the free pool instead of a timer because, as you noted, you might wind up with the cleanup of the previous request instead of the beginning of a new one.

_________________
Jeremy
http://www.beijerinc.com


Top
 Profile  
 
PostPosted: Thu Sep 11, 2014 5:37 am 
Offline

Joined: Fri Jan 31, 2014 7:28 am
Posts: 11
Sorry, I wasn't clear with my description.

HttpClientV2 itself isn't closing the connection, we are closing the connection manually once our own timeout (the timer) is reached and re-sending the command. That's where I believe the FIN, ACK is coming into play. Tossing out multiple commands over HttpClientV2 at once with only one timer is causing the timer to close improper connections.

The reason we need to handle timeouts quicker than TCP is we have quick communications. Everything is local. No response in 2s means we try again as the data is small and in reality communication is happening with 500ms.

I don't believe ConnectionClosed and EthernetError will work for us as those wouldn't happen within the 2s time frame we require.

When does a timer set itself to false? Does it set enabled to false before the timeout function is run or after the timeout function is run? What happens if a timer is already enabled and a call gets made to set enable = true? Does the time reset (i.e. back to 2s) or does the time keep running down?

I believe the following will work, although with a better understanding of how the timer is functioning will determine that.
- PoolTimer: Goes off every 500ms to send the next command in the queue (new: does nothing if ResponseTimer is enabled)
- ResponseTimer: Goes off at 2s to indicate no response and to retry previous command

So now, the connections will be limited to a single connection to be managed by a timer.


Top
 Profile  
 
PostPosted: Thu Sep 11, 2014 7:14 am 
Offline
QSI Support
QSI Support
User avatar

Joined: Wed Mar 08, 2006 12:25 pm
Posts: 881
Location: Salt Lake City, Utah
Quote:
When does a timer set itself to false? Does it set enabled to false before the timeout function is run or after the timeout function is run?


Have to look at the code for the timer itself to determine that. A OneShot timer sets enabled=false, before calling the TimeOut event override. A Periodic timer never automatically sets enabled to false.

Quote:
What happens if a timer is already enabled and a call gets made to set enable = true? Does the time reset (i.e. back to 2s) or does the time keep running down?


Setting enabled=true will reset the timer back to its original interval.

Quote:
The reason we need to handle timeouts quicker than TCP is we have quick communications. Everything is local. No response in 2s means we try again as the data is small and in reality communication is happening with 500ms.


The trick with doing this is knowing when you can recycle the underlying TCP connection. If you simply call CloseConnection on the httpclientv2 object, one of two things can happen. If a connection is pending (i.e. the TCP connection has started but not completed), the HTTPClientV2 will throw and exception and continue in the pending connection state. If the connection has been established, then we will perform an active TCP close and the object will reset its internal state.

Normally the server will perform the active close on the HTTP TCP connection. In fact, that active close is what triggers the HTTPDataReceived event to occur (although if partial data has been received when you force the close, that event will also occur).

It sounds like you have a pool of objects already. I would recommend at a minimum you structure your pool so that any objects you forcibly cancel go to the bottom of the pool and won't be reallocated for as long as possible. Also be aware that closing TCP connections from your end will cause the underlying firmware level TCP connection to enter a 2MSL state which prevents the connection from being reused for two minutes. As there are only 32 total TCP connections possible this can result in running out of connections for a time if you frequently manually close the connections.

_________________
Jeremy
http://www.beijerinc.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 7 hours


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group