SMPP session with automatic enquireLink an re-bind when needed #7

Closed
toelen opened this Issue Mar 12, 2012 · 25 comments
@toelen

Hi,

is there an example of a long-lived smpp session. I have requirement for a very long-lived smpp client session with automatic re-bind and enquireLink. What would you suggest to make as much use as possible of the existing session event notifications and the existing excutors?

Regards,
Leen

@tomjmul

Same issue. I would like to check when the underlying connection fails so that I may discard the session and connect a new one. When the underlying connection breaks, session.isBound() continues to return true.

Looked into manually unbinding the session in fireChannelUnexpectedlyClosed but seen that there is no reference to the session passed in and no way to wrap a SmppSession reference in a custom SmppSessionHandler

@jjlauer

I've been asked before for a more complete example of a long-lived session, but just haven't had time to create one. It be much appreciated if one of you were interested in at submitting one that could at worst be a draft. Ideally, we'd build a demo of an SMSC and an ESME client.

If session.isBound() continues to return true, but the connection was closed, then that sounds like a bug. Can you create a unit test to reproduce and submit a pull request?

@tomjmul
@tester5

Hi there,

Regarding the above, has a long lived session example with rebind and enquire_link etc been created? Reason being, we are able to get individual requests working such as enquire_link, submit_sm (async) and receive messages such as submit_sm_resp and deliver_sm fine. However it is not clear to us how we can turn our class into a 'server service' that runs continually so a persistent (and reliable) connection is established to the SMSC.

We are looking for guidance on best practice for this. Handling things such as:

  • handling of sequence numbers for async submit_sm_resp messages (for example we are thinking of using a session based Java HashMap to store our unique internal id and seqno)
  • handling of executors
  • handling of multiple threads (and cleanups)
  • handling of rebind in case of lost connection
  • handling of enquire_link to keep connection alive in periods of inactivity
  • handling of queuing and windowing for async messaging.

we've been through the example code though it seems there are bits and bobs in multiple classes and it's hard to get clarity on how to set up the overall framework for persistent connectivity.

Any basic example would be very helpful.

@idpromnut

We are using this library as the basis for a proxy (for a legacy system). In our design, we have both a Server and a Client, and each manage their "ends" of the communication with per-connection SMPP sequence numbers. We have implemented a simple thread running a periodic enquire_link check for both, and a simple strategy of closing connections when sequence numbers reach above a certain value (as the spec doesn't seem to specify how to handle sequence number roll over).

We actually wrote a single SmmpSessionHandler implementation that is used in both server and client parts of the proxy, so that would be where I would start. We use a per-connection SmmpSessionHandler, with the sequence number contained in that object. The client/server objects manage the task of connection establishment, management (storing the sessions in a hash map for example) and re-establishing a failed session (which I forget how exactly it is tested at the moment).

I will check today if we can release some kind of stripped down version that could be used as a demo.

@tester5

Hi idpromnut, thanks for your fast response. that would be great. is your approach Live and stable? To clarify we didn't want a full working solution but rather guidance on best practice for handling/managing persistent connections. That said, a cut down version that you have would be very helpful.

Look forward to your update. thanks again.

@idpromnut

It is going live next week, but we have been putting it under some severe load testing in preparation for this. And just to clarify, if I can release anything, it will be useful as an example design only, so what you're looking for.

@tester5

that sounds good, thank you.

regarding your comment about sequence no rollover, I found the following in the CH source code in the following package: com.cloudhopper.smpp.util.SequenceNumber

  • Utility class for atomically generating SMPP PDU sequence numbers. This
  • implementation will atomically increment the sequence number and wrap it
  • around back to 1 when it hits the max 0x7FFFFFFF.

Is that not sufficient for your needs?

@jjlauer @idpromnut on a different note we are trying to work out whether we need to create a DefaultSmppClient or DefaultSmppServer based on our requirements above. Initially we would operate as an ESME and be able to:

-send/receive SMS messages
-receive submit_sm-resp messages
-receive delivery receipts
-maintain persistent connection and auto reconnect

based on that do I need to create a DefaultSmppClient or DefaultSmppServer?

@idpromnut

You would need to use DefaultSmppClient for your needs. We just use it as is, no modifications. We do pass it our own SmppSessionHandler implementation when we bind the client. We also have a thread running which is monitoring the client which is checking the SmppSession which is returned by SmppClient.bind(). Specifically, we look at three conditions that trigger a reconnect:

session == null (duh :)
(!session.isBound() && !session.isBinding() && !session.isOpen())
enquire_link_resp not received within a certain deadline

Hope that helps!

@tester5

Hi yes that helps a lot thank you. We have reconnect working although we do sometimes receive an error (I will raise this as a separate issue). I actually got a fair bit of help looking at PerformanceClientMain where we can set up multiple sessions using the Thread Executor (we wish to maintain 2 permanent active Transceiver sessions/connections). We also have kept the CountDownLatch that waits until the sessions are established before attempting to poll for new messages. a lot has been removed though also.

My main query is with Windowing and how that works. I understand the concept, however not sure if I'm missing something. I would like to set WINDOW_SIZE to 50. To simplify my scenario (see performance client main example):

1) I set up a Client session with Window size set to 50
2) In the run method I have a for loop that will loop 150 times
3) in each loop I generate a submit_sm with a unique message and send it asynchronously using sendRequestPdu function, e.g. session.sendRequestPdu(submit, 30000, false);
4) in fireExpectedPduResponseReceived I process the responses
5) in firePduRequestReceived I process the Delivery receipts

Is there anything else major I need to do to manage "Windowing" or is this already managed?

@idpromnut

So far as I understand it, "windowing" is handled by the library internally and so there should be no need to "manage" anything relating to it. We use the synchronous sendRequestPdu() method with a timeout with a catch to handle the cases where a request could not be sent due to a full window for longer than the specified timeout. That being said, be careful setting the window size to high; that window is for the number of "inflight" request (i.e. requests that you send that you have not received responses for yet). This window should be set according to the capabilities of the SMSC that you are speaking to (for example, our provider's SMSC will start sending back throttling responses if we more than 20 requests inflight at a given instant in time).

@tester5

thanks for the fast response. the comments are very helpful and help us determine what is already covered as well as what we need to configure for our own needs.

Our SMSC has already suggested inflight (window) size of 50 is fine for them (but no more!). So if we have 150 messages to process as described above are you saying that the library would handle and send say 50, leave 100 in a queue, until at least 1 response has been received? So, for example, if 50 go out, 100 are queued, we receive 5 responses back from first 50, then another 5 are released from the queue bringing the queue to 95?

Is that example what happens by the library?

@idpromnut

That is my understanding of the window mechanism, and yes, I believe the library performs that function. If you are using the asynchronous call to send requests, you want to have a look at the WindowFuture that you receive back to give you a hint as to what happened regarding a possible timeout due to the window being full for too long.

@greglwood

I know this thread is a little old but did anyone ever provide or find a really good example of a long lived session?

@fjordansilva

+1, Is there any example?

@krasa

+1 example anyone? I am going to need this feature, so it makes me think that using JSMPP would be better just because of this.

@smallgod

hello @krasa et al.. please visit this page: https://github.com/wizardjedi/my-spring-learning/wiki/Twitter-cloudhopper the page is in Russian but you can translate it to English. It will be very helpful. has a couple of examples, even the one of a persistent connection with SMSC (auto-reconnect/rebind)

@krasa

@smallgod Thanks, I have done something similar.. but without duplicating the state, and if enquire link fails I immidiatelly destroy session and try to reconnect (not sure if it is the right way)

https://github.com/krasa/cloudhopper-smpp/tree/persistent-connection/src/test/java/com/cloudhopper/smpp/demo/persist

@batman09

@jjlauer I want cloudhopper to pull SMS messages that arrive at my sms gateway continuosly .I am able to push messages to cloudhopper server from a client but I want cloudhopper to pull messages that are sent by a client.any helper classes to achieve this

@idpromnut
@batman09

@idpromnut my scenario is i have an OpenSMPP (simulator) that is run on an ip address and port .So whenever i start the simulator at particular ip and port ,cloudhopper should able to bind (i.e send bind request) to this simulator.So that when i send message from my simulator ,cloudhopper pulls the message from simulator and it (cloudhopper) should not unbind as long as simulator is running .

@idpromnut
@xgp xgp closed this Jan 5, 2015
@NaveenNew

Is it possible to send messages to SMSC using one Smppsession (or a session that lasts long )because binding & unbinding for every single msg has resulted in creating large number of bind requests at SMSC .

Due to this load ,SMSC is failing to receive bind requests and we are receiving the error "com.cloudhopper.smpp.type.SmppTimeoutException: Unable to get response within [3000 ms]"
@jjlauer @idpromnut @tester5 @toelen @tmuldoon-aimia

@idpromnut
@NaveenNew

Can you share the code or a snippet to implement this @idpromnut .Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment