Author Topic: cleaning up a socket with no connection  (Read 15011 times)

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
cleaning up a socket with no connection
« on: April 17, 2014, 10:50:58 AM »
Hi Mark,
  What is the best way to clean up a socket if a connection isnt established?  I do the following steps:

  1. get a socket fnGetTCP_Socket(..)
  2. then call fnTCP_Connect(..) and set a 2 second timer using uTaskerMonoTimer(..)
  3. if a connection is established, then stop timer, if not then:
        a.  fnTCP_close() is called..
        b. TCP_EVENT_CLOSED within the callback is processed and fnReleaseTCP_Socket() is called.

Should the fnTCP_close() only be carried out if a connection is made, or simply call fnReleaseTCP_Socket()?

What I am noticing is the next time I am carrying out the above for fnGetTCP_Socket() ucTCP_state = TCP_STATE_ESTABLISHED for the previous fnGetTCP_Socket()


Best Regards
Neil


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #1 on: April 18, 2014, 12:02:27 AM »
Hi Neil

I think that fnTCP_close() is the best thing to do - it will set the socket to TCP_STATE_CLOSED (and ensure that an present activity is terminated).

Don't use fnReleaseTCP_Socket() in the call-back since it will free the socket "before" the close has finished operation with it - the result is that the socket it not freed but set to TCP_STATE_CLOSED.
When you subsequetly call fnGetTCP_Socket() it is then getting a "new" socket and the old one still exists (in the closed state). After some repetitions the socket pool will probably become exhaused and you won't be able to get any more to work with.

In fact there is no real need to release a socket if you will be using it again later - just keep the original one and reuse it.

I couldn't see why you would get a new socket with an established state since a close certainly puts it to the closed state and a new socket will originally have the state TCP_STATE_RESERVED.

Possibly the call for a new socket is failing (check that the returned valus is >= 0) and maybe you are using the error value as a socket number and then it looks to have a different state (?)

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #2 on: April 18, 2014, 07:47:54 AM »
Hi Mark,
  Thanks for the reply.

When the connection cant be established, and I call fnTCP_close() , it takes a while for the TCP_EVENT_CLOSED in callback to be called, is this normal?.

If I don't use fnReleaseTCP_Socket(), will the socket be safe to reuse when the TCP_EVENT_CLOSED is called? If not when is it safe to reuse it?

Best Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #3 on: April 18, 2014, 08:10:13 PM »
Neil

It depends on the state of the connection as to how long it may take to close.

If there is no peer and the connection is repeating connection attempts I would expect it to close immediately, however a connected peer may not want to close and can hold the connection open until it has completed what it wants to complete - usually sending some extra data. If there is no peer you will also receive TCP_EVENT_ABORT after the connection attempt gives up.

A close may be repeated a few times if there was a connection before the connection is force-reset (when no response because the peer was , for example, powered down during a connection)

To monitor this you can use the fnGetTCP_state() call to get the state that the socket is in when you start the close.

After you receive the closed event the socket will be available for reuse - again calling fnGetTCP_state() will help to be sure. After a close it always goes to TCP_STATE_CLOSED which means that it is not in use (but still bound so it can be used for another connection).

Regards

Mark




Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #4 on: April 19, 2014, 12:06:44 PM »
Hi Mark,
 
After I get a  TCP_STATE_CLOSED , I reuse the socket again. I also use the fnGetTCP_state() and I sometimes get a TCP_STATE_TIME_WAIT. So even though the socket is closed its not always available? And it looks like I should always use the  fnGetTCP_state() when getting a socket from the pool?

Best Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #5 on: April 19, 2014, 02:26:40 PM »
Hi Neil

See the state transition diagram here: http://www.utasker.com/docs/uTasker/TCP_SE_DIAG.PDF

If you had a connection established and close actively the socket goes to the TCP_STATE_TIME_WAIT state for typically 2 minutes after you have received the TCP_EVENT_CLOSED event.

Strictly according to the TCP specifications a socket should not be reused within this period of time (this has something to do with old packets belonging to the connection bouncing around in the Internet for some time and so this ensures that if they are received during this period there will be no matching socket for them - the packet won't be recognised as belonging to the "new" connection).
However this restriction doesn't make much sense in small emebdded systems since it would require additional sockets being available for use during this time, therefore the option REUSE_TIME_WAIT_SOCKETS is set as standard and allows the socket to be reused from this state (as if it were in the closed state).

Therefore you can consider the TCP_STATE_TIME_WAIT state to be equivalent to the TCP_STATE_CLOSED state.

When getting a socket from the pool it is adequate to check that the socket returned is valid (i.e. it is not a negative value). The state will be TCP_STATE_RESERVED reserved in this case (when valid) and so using fnGetTCP_state() immediately would always return this state and so not deliver any extra infomration.

Regards

Mark



Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #6 on: April 19, 2014, 04:04:58 PM »
Hi Mark
  if i treat the _WAIT_STATE as _CLOSED my application doesnt make a connection, and wait state is returned. I make a few samples every ten seconds, and if i check the status first, and only use when marked closed, i never get an error, the socket is cleared by the next ten seconds. My windows application it connects to is on the same LAN.

regards
neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #7 on: April 20, 2014, 03:04:41 AM »
Hi Neil

I have just done some tests but can't reproduce a problem with connecting when the socket is still in the TCP_STATE_TIME_WAIT state.
Perhaps you could check the program flow as follows:
1) fnTCP_Connect() is called when the socket is in the TCP_STATE_TIME_WAIT state.
2) In fnTCP_Connect() the following is true:
    if (!(ptr_TCP->ucTCP_state & (TCP_STATE_RESERVED | TCP_STATE_LISTEN | TCP_STATE_CLOSED))) { // are we in an invalid state?
meaning that the REUSE_TIME_WAIT_SOCKETS option comes into play.
3) This then checks whether the socket is allowed to be reused (not still active in some way) by doing
        if (ptr_TCP->ucTCP_state & (TCP_STATE_FIN_WAIT_2 | TCP_STATE_TIME_WAIT)) {
            fnNewTCPState(ptr_TCP, TCP_STATE_CLOSED);
            ptr_TCP->event_listener(_TCP_SOCKET_MASK(ptr_TCP->MySocketNumber), TCP_EVENT_CLOSED, ptr_TCP->ucRemoteIP, ptr_TCP->usRemport); // {56}
        }
        else {
            return (SOCKET_STATE_INVALID);
        }

4) Assuming TCP_STATE_TIME_WAIT, it should set the closed state and also inform the application (again) that the socket has closed and afterward start opening the connection (by sending a TCP SYN). The return value is the USOCKET number (i.e. >= 0)
5) Assuming it was not in TCP_STATE_TIME_WAIT it would return the error SOCKET_STATE_INVALID

You have noted that the wait state is returned but I don't see such a return from fnTCP_Connect().

I have attached my tcp.c file so that you can verify that there are no differences (in this area) to yours.

Regards

Mark


Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #8 on: April 20, 2014, 09:30:02 AM »
Hi Mark,
  I have an old tcp.c, the last update I have is 29/12/2009 {16}, which doesn't include re-using TCP_STATE_TIME_WAIT. I tried compiling your file , but got lots of errors (which I suspect because of old headers too).   Would it be possible to get a copy of the headers ?

Many Thanks

Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #9 on: April 20, 2014, 06:06:46 PM »
Hi Neil

I would just copy the option's code since there may be compatibility issues taking the complete file and tcpip.h. It does however explan why you can't always reuse the socket immediately.

Don't forget that you can always download the most up to date release and older versions in the corresponding forum thread. By checking through the release notes and the headers in each file patches, improvements and extensions care quite easy to identify.

Regards

Mark



Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #10 on: April 20, 2014, 06:52:41 PM »
Hi Mark,
  I noticed the tcp.ip you attached earlier had changes in 2014, does the latest patch have these updates?  I tried downloading the patch, but cant find my password, can you check if it is still valid, if so please email it to my address?

Many Thanks

Best Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #11 on: April 20, 2014, 08:27:27 PM »
Neil

I mailed you the password.

I think that this is quite an old option since it is already in the V1.4.0 release for M522xx.

The latest M522xx release version is V1.4.11, which doesn't have all latest development changes (mainly new features) but is stable.

Regards

Mark


Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #12 on: April 20, 2014, 08:34:49 PM »
Hi Mark

Thanks for that, I look forward on getting the password.

I looked at the latest patch SP9 and it says its 1.30 on the zip file header, is this actually 1.40?

regards
Neil

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: cleaning up a socket with no connection
« Reply #13 on: April 21, 2014, 10:55:54 AM »
Hi Mark,
   I am still having the same issues (after copying over tcp.c). I placed some messages on the screen and debugged the code and this is what is happening.

The first time around TCP_STATE_CLOSED is called and I mark the socket as to be used again (within my own code).  When I try to re-use the socket the TCP_STATE_CLOSED is called again , as within the fnTCP_Connect() function :

    if (!(ptr_TCP->ucTCP_state & (TCP_STATE_RESERVED | TCP_STATE_LISTEN | TCP_STATE_CLOSED))) { // are we in an invalid state?
#ifdef REUSE_TIME_WAIT_SOCKETS
          if (ptr_TCP->ucTCP_state & (TCP_STATE_FIN_WAIT_2 | TCP_STATE_TIME_WAIT)) {
            fnNewTCPState(ptr_TCP, TCP_STATE_CLOSED);
         ptr_TCP->event_listener(ptr_TCP->MySocketNumber, TCP_EVENT_CLOSED, ptr_TCP->ucRemoteIP, ptr_TCP->usRemport); <<<  gets called again.
        }
        else {
            return (SOCKET_STATE_INVALID);
        }

As I mark each socket to be reused within the TCP_STATE_CLOSED, getting called again, simply marks as re-use. I checked the value of ptr_TCP when TCP_STATE_CLOSED was called and when the above was called to make sure the pointer address was the same, and they were.

I assume this is the reason why my code always works when calling fnGetTCP_state(..) before reusing the socket.

 Looking at usOurPort parameter within fnTCP_Connect(..) function, should this be set to 1 if reusing a socket ? I noticed withing the fnTCP_Connect(..) function ,fnGetFreeTCP_Port() gets called if usOurPort=0. I tried setting to 1 , but still no luck.



Regards
Neil


« Last Edit: April 21, 2014, 04:07:58 PM by neil »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: cleaning up a socket with no connection
« Reply #14 on: April 21, 2014, 04:51:50 PM »
Neil

If you receive a TCP_EVENT_CLOSED when connecting it means that the socket is being re-used. If this (second closed) event is disturbing in some way you could remove the call-back - possibly a different event would be more meaningful (TCP_EVENT_SOCKET_REUSE for example) and the possibility to even disallow the re-use if the application decided to leave the WAIT state (although I wouldn't expect it to be actually used).

In any case, the state must now have been set back to TCP_STATE_CLOSED and the new connection attempt initiated. Therefore I expect you to see the TCP SYN sent out at the new connection attempt.

The usOurPort parameter can be 0 if the source port to be used for the connection is to be random. If set to non-zero the passed value will be used as source port number. The value of this parameter doesn't have anything to do with whether the socket is reused or not and determines the source port of the connection when it is established in both cases. The value of 1 would be strange since non-standard applications generally use value sin the range of 49152 to 65535 (dynamic port range) - the value of source port used doesn't have any effect in many cases (only realyl when the peer is expecting a certain value to be set).

Regards

Mark