Home AMX User Forum AMX Technical Discussion

Issue with?IP socket to keep connected all the time

Hi

I made a little piece of code to keep open an IP connection for some devices that I control in IP and don't want to bother to keep connection open. Unhappy when connection is broken (device offline or cable disconnected), the module goes in a loop of IP Socket already closed and never succeeds to get connection back online or if it does, just a very short time. I'm killing my head on this as I don't see the issue in my code.

Any ideas ? I guess it's something obvious but not seeing for now :(

Vinc?n
MODULE_NAME='socket-ip' (dev dvSocket_IP,CHAR IP[30],CONSTANT INTEGER PORT)
(***********************************************************)
(*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_DEVICE

dvMaster = 0:1:0

(***********************************************************)
(*               VARIABLE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_VARIABLE

CONSTANT INTEGER ID_Timeline = 1
LONG TEMPS[1] = {2000}
INTEGER ETAT // 1: Connect?, 2:Erreur

(***********************************************************)
(*       MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW           *)
(***********************************************************)
DEFINE_MUTUALLY_EXCLUSIVE

(***********************************************************)
(*                THE EVENTS GO BELOW                      *)
(***********************************************************)
DEFINE_EVENT

DATA_EVENT[dvMaster]
    {
    ONLINE:
    {
    ETAT = 2
    TIMELINE_CREATE(ID_Timeline,TEMPS,1,TIMELINE_RELATIVE,TIMELINE_REPEAT)
    IP_CLIENT_OPEN(dvSocket_IP.Port,IP,Port,1)
    }
    }

DATA_EVENT[dvSocket_IP]
    {
    ONLINE:
    {
    ETAT = 1
    TIMELINE_SET(ID_Timeline,0)
    }
    OFFLINE:
    {
    ETAT = 2 // d?connect?
    IP_CLIENT_CLOSE(dvSocket_IP.Port)
    WAIT 5
        {
        TIMELINE_SET(ID_Timeline,0)
        IP_CLIENT_OPEN(dvSocket_IP.Port,IP,Port,1)
        }
    }
    ONERROR:
    {
    ETAT = 2 // d?connect?
    IP_CLIENT_CLOSE(dvSocket_IP.Port)
    WAIT 5
        {
        TIMELINE_SET(ID_Timeline,0)
        IP_CLIENT_OPEN(dvSocket_IP.Port,IP,Port,1)
        }
    }
    }

TIMELINE_EVENT[ID_Timeline]
    {
    SWITCH(ETAT)
    {
    CASE 1: // Connect?
        {
        TIMELINE_SET(ID_Timeline,0)
        }
    CASE 2: // D?connect?
        {
        IP_CLIENT_CLOSE(dvSocket_IP.Port)
        WAIT 5
        {
        IP_CLIENT_OPEN(dvSocket_IP.Port,IP,Port,1)
        TIMELINE_SET(ID_Timeline,0)
        }
        }
    }
    }

(*****************************************************************)
(*                       END OF PROGRAM                          *)
(*                                                               *)
(*         !!!  DO NOT PUT ANY CODE BELOW THIS COMMENT  !!!      *)
(*                                                               *)
(*****************************************************************)

Comments

  • This is what I see:
    ONERROR handler closes the port, then the timeline event closes it again, which will trigger an error.
    Also I don't think OFFLINE handler needs to close the port as it is triggered by the closing of a port.
  • viningvining Posts: 4,368
    Yep, when the device goes offline you issue a IP_Close when the socket is already closed so the master issues the onerror for trying to close and socket that's already closed but then your ONERROR handler processes the error and issues another close and then tries to open. for now I would just get rid of the ONERROR code or add the ONERROR function so you can do things based on what type of error you're receiving. Do nothing on a socket already closed error but on other errors you might want to attempt a reconnect but ususally those would be after a much longer wait. You also don't really need the IP_Close in the OFFLINE event but I have seen times where it does help but that could have been many, many master firmware revs ago. The of course there's the flip side with the onerror when tyou then try to open the socket in both the offline and onerror cuz in an offline event and because of the already closed socket error they're both going to try and open so the offline should try an ope first followed by the onerror but then you should get another error stating the socket is already open which throws that error which closes the socket and then the offline, onerror repeats all over again. I also like to use tracking variables for my connection states

    0 disabled
    1 offline
    2 pending
    3 online
    4 communication established

    so that if I issue an open I set the flag to pending so if I have an error reconnect or any other type of reconnect I can check my tracking and not attempt a reconnect unless I'm offline or disable. If my var is 2 or above I do nothing except timeout the pending var after say 5 seconds if I get no online event.
  • JasonSJasonS Posts: 229
    I have template code for my IP com modules that works this way. I do not send an IP_Close in the OFFLINE or ONERROR event and I have never had any issues with it.
  • a_riot42a_riot42 Posts: 1,624
    By the time OFFLINE is executed the socket is already closed. I very rarely ever use the IP_Close command. Either the socket closes because the server sets the FIN bit so it closes automatically, or an error occurred taking the socket offline, and thus is closed anyway. The only time I ever use IP_Close is if I want to deliberately close a socket that is currently open, which is almost never, or something read from the socket indicates the need to close it, which is also rare.
    Paul
  • vincenvincen Posts: 526
    Thanks for explanation but for me it was mandatory to do the IP_Client_Close each time the socket is dead. Nice to hear it's no more necessary but it does not explain why the socket never reconnects after lost of connection no ?

    JasonS: Would you mind to share your IP com modules ?
  • JasonSJasonS Posts: 229
    vincen wrote: »
    JasonS: Would you mind to share your IP com modules ?

    Due to contractual obligations I cannot share the actual code. But I am happy to help any other way.
  • Since I've started dealing with a lot of inbound IP connections from SDX and DX-RX units, I've had to revamp my device event codestack. I set or clear an "online" flag based on device events, then use functions that check flag state before issuing any Online of Offline commands for outbound connections. I also use a timeline to wait a few seconds before trying reconnect, then keep upping the retry time if a connection error keeps happening. That keeps those quasi-ghost connection errors from cropping up. Unfortunately, the spaghetti mess of code I've created to deal with the SDX and DX-RX units is way more complicated, and still doesn't seem to trap and cover every type and timing of device event. Anywhere from 3 seconds to 3+ minutes to come online is a pretty wide range of conditions to cover, especially when the longer it takes to connect, the more likely someone will end up force rebooting a device or perhaps the entire equipment rack, re-starting the connection process, or even a whole bunch of connection processes, all over again.
  • Try this module. All settings are made through code so connections can be changed on the fly. Also, it can be used in conjunction with NetLinx comm modules to handle their IP connections. I've also added a main.axs file to show how to incorporate the module.

  • ericmedleyericmedley Posts: 4,177

    Sorry to jump in late - but I notice you chose IP port 1 in the code. Isn't port 1 in sue by the master firmware? I usually start my IP ports at 3.

Sign In or Register to comment.