none
Custom TCP Adapter using WCF LOB SDK SP2 RRS feed

  • Question


  • Heya all

    I am writing an adapter (aimed at BizTalk) using the LOB SDK (SP2) to receive messages from some legacy systems, and am having trouble figuring out how to slot the socket code in to the various SDK interfaces.

    I am trying to create a synchronous inbound adapter, so am implementing IInboundHandler, and of course IConnection.

    I am uncertain at what point in the SDK interface calls I need to create a TCP socket to listen on, when I should bind it, when I should start listening, accept connections, etc.

    I think I need to set up a TCPListener in IConnection.Open, but only start it listening in IInboundHandler.StartListener. But how do I then accept connections? Do I need to block in IInboundHandler.TryReceive until a message arrives? What about multiple incoming connections?

    Or should I create/bind the listener in IConnectionFactory, and each IConnetion instance signifies a new TCP connection? (in its own thread?)

    Haven't been able to figure whether I can use/have to use blocking or async sockets - is the connection pool implicitly threaded per connection, or would I manually need to manage threads? Is using the async API the best way to handle this? If so, how do I implement IInboundHandler.TryReceive or IInboundHandler.WaitForMessage?

    Thanks in advance for any help with this - I'm nearly there, I feel like I'm missing one vital bit of information before it all starts to make sense!

    Thanks

    Simon





     

    Tuesday, June 16, 2009 6:00 PM

Answers

  • Hi,

    I think each IConnection signifying a new TCP connection will be a good approach. The connection pool does not have a thread per connection in the connection pool. Maybe you could do this - in your StartListner, you could start a thread that listnens for TCP connection, and if there is something that could be written to some object. The WaitForMessage, when called would just look at this object, and if there is something written into it by the listening thread, create a message out of it. I don't know if this makes sense in your scenario :)

    Thanks,
    Manas
    • Marked as answer by Simon Davy Wednesday, June 17, 2009 9:26 AM
    Wednesday, June 17, 2009 4:54 AM
  • Hi Simon,

    Yes - I did not consider that you'll have multiple requests coming in.

    Here is the seqnence of events :

    IConnectionFactory Created -> IConnection created -> StartListner called -> [WaitForMessage/TrReceive] Called.

    If Inbound transactions are enabled, then waitformessage is called before calling tryReceive, else only tryReceive is called (similar to what happens on a WCF Channel when called by a serviceHost)

    Also, the adapter cannot control the creation of IConnections at its will.

    So here is what I think you can do:

    1. In StartListner, start a thread that will listen for incoming TCP requests, and open as many TCP sockets as needed (and threads to process them too)
    2. These threads would write the incoming TCP 'message' to a queue that sits in IInboundHandler / higher up the stack
    3. TryReceive just checks if there is something in the queue, and if yes, gives it out as a message

    You'll have to ensure that the queue is placed sufficietly high up in the stack as the IConnection can be discarded by the SDK in case of an error. Also, set your receive timeout to Timeout.MaxValue to ensure that WCF service host does not abort the WCF channel while your threads keep running.

    Hope this helps!
    Manas

    • Marked as answer by Simon Davy Thursday, June 18, 2009 7:39 AM
    Thursday, June 18, 2009 4:27 AM
  • IConnectionFactory should be good enough. I dont think you'd want a static queue for the incoming messages - that would mean if you have multiple receive locations in the same host, they'd start sharing the same queue - somethng that I think you may not want.

    As you describe it, the listen socket can be made static and could again sit in IConnectionFactory - that would really depend on your requirement.
    • Marked as answer by Simon Davy Thursday, June 18, 2009 2:38 PM
    Thursday, June 18, 2009 9:31 AM

All replies

  • Hi,

    I think each IConnection signifying a new TCP connection will be a good approach. The connection pool does not have a thread per connection in the connection pool. Maybe you could do this - in your StartListner, you could start a thread that listnens for TCP connection, and if there is something that could be written to some object. The WaitForMessage, when called would just look at this object, and if there is something written into it by the listening thread, create a message out of it. I don't know if this makes sense in your scenario :)

    Thanks,
    Manas
    • Marked as answer by Simon Davy Wednesday, June 17, 2009 9:26 AM
    Wednesday, June 17, 2009 4:54 AM

  • Thanks - that's getting me further along on the right lines :)

    What I could really do with is some documentation on when and how the SDK creates IIConnection and IInboundHandlers instances. Or is that up to me?
    Wednesday, June 17, 2009 9:37 AM
  • I am assuiming the process is like so:

    SDK creates an IConnectionFactory

    Some event occurs?

    SDK creates an IConnection via the factory (how/when would an additional new connection be created?)

    SDK creates a new IInboundHandler with that connection.

    SDK calls IInboundHandler.StartListener()

    In a loop, SDK calls IInboundHandler.WaitForMessage() OR IInboundHandler.TryReceive() (dependant on the configuration of the adapter?) to get messages.

    Is that even close? :)


    Wednesday, June 17, 2009 10:32 AM
  • Hi Simon,

    Yes - I did not consider that you'll have multiple requests coming in.

    Here is the seqnence of events :

    IConnectionFactory Created -> IConnection created -> StartListner called -> [WaitForMessage/TrReceive] Called.

    If Inbound transactions are enabled, then waitformessage is called before calling tryReceive, else only tryReceive is called (similar to what happens on a WCF Channel when called by a serviceHost)

    Also, the adapter cannot control the creation of IConnections at its will.

    So here is what I think you can do:

    1. In StartListner, start a thread that will listen for incoming TCP requests, and open as many TCP sockets as needed (and threads to process them too)
    2. These threads would write the incoming TCP 'message' to a queue that sits in IInboundHandler / higher up the stack
    3. TryReceive just checks if there is something in the queue, and if yes, gives it out as a message

    You'll have to ensure that the queue is placed sufficietly high up in the stack as the IConnection can be discarded by the SDK in case of an error. Also, set your receive timeout to Timeout.MaxValue to ensure that WCF service host does not abort the WCF channel while your threads keep running.

    Hope this helps!
    Manas

    • Marked as answer by Simon Davy Thursday, June 18, 2009 7:39 AM
    Thursday, June 18, 2009 4:27 AM
  • Great, thanks - that kind of sorts things out for me in my head.

    I am using the async socket API to handle multiple long-lived connections, and am putting the incoming messages in an incoming queue, as you suggest.

    But I'm not sure where the best place for it is. You say "sufficiently high up the stack" - is IConnectionFactory high enough? Or do I need a static variable or singleton? 

    The bound listen socket has the same stack height concern, as I think I only want there to be one per machine, regardless of how many IConnectionFactorys, IConnections or IInboundHandlers there are. 

    This would suggest a static variable or singleton is need to store these two instances - would that make sense?

    Thanks for you input - very useful :)
    Thursday, June 18, 2009 9:14 AM
  • IConnectionFactory should be good enough. I dont think you'd want a static queue for the incoming messages - that would mean if you have multiple receive locations in the same host, they'd start sharing the same queue - somethng that I think you may not want.

    As you describe it, the listen socket can be made static and could again sit in IConnectionFactory - that would really depend on your requirement.
    • Marked as answer by Simon Davy Thursday, June 18, 2009 2:38 PM
    Thursday, June 18, 2009 9:31 AM