Loosing my sockets after Reset Origin???

laythea
2010-09-03
2010-09-06
  • laythea - 2010-09-03

    Hi,

    Hoping someone here has dealt with sockets in v3 of codesys....

    I have some socket handles which i store in a persisant variable GVL.

    My codesys (v3) application opens the socket handles. This is fine for reset warm, cold, on-line edits, download and run etc but I have a problem where if I do a Reset origin, I loose the handles to the sockets (they are initialised back to 0xFFFFF.... without the windows socket handles actually being closed).

    Then when I try and start the application again after the reset origin I get a socket bind() error (The provided address is already in use - ERR_SOCK_ADDRINUSE) when i try to create the socket handles. This is expected because although the codesys application has lost the handle references, the sockets are still open in windows xpe. I have to actually Stop the SP RTE runtime, redownload, and restart the application before I can get my sockets back. When I stop the SP RTE runtime, it is only at this point where windows disposes of the socket handles.

    I guess these are my questions....

    1. Should the "Reset Origin" not close the Windows handles for me?
      If it did do this, then I would not get the bind "address already in use" error.

    2. Failing point 1, I need to be able to actually close the socket handles in response to a reset origin command.
      Is there any way to subscribe to application events such as reset origin, run, stop etc?

    3. Failing point 2, is there a better way of maintaining socket handles so that I do not have to manually Stop and
      start/redownload SP RTE to get my sockets back?

    4. Is there any way of closing a socket without having a reference to its handle? Ie. Discovering its handle
      from the socket address (port, ipaddress etc)

    Thanks for any help!

    Laythe

     
  • TimvH

    TimvH - 2010-09-06

    I had the same behavior for serial ports.
    You need to close the port before stopping the application otherwise the port remains opened untill the SP RTE V3 service is stopped.
    In V2.3 there are systems events (Tasks) which can call a POU. E.g. the system even stop or reset could call a POU which can close the port just before the application is actually stopped.
    In the help of V3.4.1.0 is described that this is not yet implemented.

    It might be that the new "network" library 3.4.1.0 in the category "USE CASES" now handles this better.
    Did you use the FB's of this library?

     
  • laythea - 2010-09-06

    Hi Tim, thanks for the reply.

    No, i have been using v3.3 SP2. I have upgraded now and will have a play with the new libraries. I am currently using the SysSocket library and making calls SysSockCreate() etc.
    I will let you know how I get on!

    Thanks again
    Laythe

     
  • laythea - 2010-09-06

    Cheers Tim,

    It seems we can register against application events with V3 . I've now got my code closing the windows socket on a EVT_StopDone event, and hey-presto no more socket errors!

    For anyone interested in this....

    Add CmpApp and CmpEventMgr libraries.

    Then declare ApplicationEventHandler:

    FUNCTION_BLOCK ApplicationEventHandler IMPLEMENTS ICmpEventCallback
    VAR_INPUT
    END_VAR
    VAR_OUTPUT
    END_VAR
    VAR
       res: UDINT;
       evt1: UDINT;
       evt3: UDINT;
       cb1: UDINT;
       cb3: UDINT;
    END_VAR
    

    Add 3 methods to this FB:

    EventCallback:

    METHOD EventCallback : UDINT
    VAR_INPUT
       pEventParam : POINTER TO EventParam;
    END_VAR
    VAR
    END_VAR
    IF( pEventParam^.EventId = EVT_StartDone ) THEN
       ApplicationStart(); 
    END_IF
    IF( pEventParam^.EventId = EVT_StopDone ) THEN
       ApplicationStop();
    END_IF
    

    There are other events you can subscribe to but I havnt played with any of them... they are listed in CmpApp library. ApplicationStart()/ApplicationStop() are just my own PRG blocks....

    FB_init:

    METHOD FB_init
    VAR_INPUT   
       bInitRetains : BOOL;
       bInCopyCode : BOOL;
    END_VAR
    VAR
    END_VAR
    // Register on event EVT_StartDone
    evt1 := EventOpen(16#10002, 16#2, res);
    cb1 := EventRegisterCallback(evt1, THIS^, res);
    // Register on event EVT_StopDone
    evt3 := EventOpen(16#10004, 16#2, res);
    cb3 := EventRegisterCallback(evt3, THIS^, res);
    

    FB_exit:

    METHOD FB_exit
    VAR_INPUT
       bInCopyCode : BOOL;
    END_VAR
    VAR
    END_VAR
    (* register on event EVT_StartDone *)
    res := EventUnregisterCallback(evt1, cb1);
    EventClose(evt1, res);
    (* register on event EVT_StopDone *)
    res := EventUnregisterCallback(evt3, cb3);
    EventClose(evt3, res);
    

    Then make sure you instantiate an instance of the ApplicationEventHandler FB: Eg:

    mApplicationEventHandler:ApplicationEventHandler;
    

    This is based on the "Sys Info" example in the FTP folder. I'm not sure why 3S don't document things like this properly....I had to go poking around in the HTML documentation to guess EVT_StopDone = 16#10004 based on the example of EVT_StartDone being equal to 16#10002 and EVT_StopDone being listed 2 places down. Not difficult, just a pain in the butt!!

    Anyway, cheers
    Laythe

     
  • TimvH

    TimvH - 2010-09-06

    Perfect !!! Thanks for the info.

     

Log in to post a comment.