sungsilnom / jsmpp

Automatically exported from code.google.com/p/jsmpp
Apache License 2.0
0 stars 0 forks source link

Slow SMS processing #71

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
I have implemented JSMPP in a project but speed of sending sms is very slow
can anybody please help on this because i have very high volume
transactions requirements.

Original issue reported on code.google.com by farooq.z...@gmail.com on 5 May 2010 at 11:27

GoogleCodeExporter commented 8 years ago
Please mention something more about your project.

1) Kind of system- asynchronous or synchronous messaging
Asynchronous messaging would be faster. Keep sending thread and receiving thread
separate.
2) Keep some code sample.

Original comment by hbkricha...@gmail.com on 6 May 2010 at 7:56

GoogleCodeExporter commented 8 years ago
I am just using there threee lines if i need to change anything for fast sms 
sending.
I only have to send sms there is no sending but right now its using 50 of CPU.

SMPPSession session = session.connectAndBind(SMSCIp, port, new
BindParameter(BindType.BIND_TX,systemId,password,systemType,TypeOfNumber.UNKNOWN
,NumberingPlanIndicator.ISDN,addressRange));

session.submitShortMessage("CMT",
TypeOfNumber.ALPHANUMERIC,NumberingPlanIndicator.UNKNOWN,source,
TypeOfNumber.UNKNOWN, NumberingPlanIndicator.UNKNOWN, destination, new 
ESMClass(),
(byte)0, (byte)1,   null, null, new 
RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT),
(byte)0, new GeneralDataCoding(false, false, MessageClass.CLASS1,
Alphabet.ALPHA_DEFAULT), (byte)0, smsText.getBytes());

session.unbindAndClose();

Original comment by farooq.z...@gmail.com on 7 May 2010 at 8:05

GoogleCodeExporter commented 8 years ago
Hi Farooq,

This is what I was telling you the other day. The session.submitShortMessage() 
you
are using in your code is a synchronous call. It returns you the messageId as a
String. This is later used to keep track of the DR.

The problems with the code:

a) The difficulty here is that when you make a synchronous call, you will block 
your
sending thread to receive the response from the SMSC vendor. Next message would 
be
send only after receiving the response. This makes your application slow.

b) You are trying to establish a new session with the SMSC for each message. 
This can
prove to be fatal. For every sms, your application will have to wait for the 
session
establishment. It involves many i/o operation like establishing socket 
connectivity,
sending packets, closing sockets and associated streams. This would take a lot 
of
time. You can think of just creating one connection to the SMSC vendor and 
sending
all your packets through that connection.

My suggestion:
1) Establish a direct socket connectivity to the operator ip and port.
2) Use the DefaultPDUSender class to send packets asynchronously to the 
operator's
output stream.
3) Keep a thread that reads packets from the stream. I would suggest you not to 
use
DefaultPDUReader for the current version. It has a small issue with reading 
packets.
Please refer to issue no 65 for better implementation. You can modify the code 
in the
DefaultPDUReader class if you have any doubts.
4) Try sending a bind request to the operator using sendBind() in 
DefaultPDUSender.
Dont confuse with the byte[] returned by it. It is just a byte[] representation 
of
your pdu. 
5) Now a packet would be send back to you by the SMSC. It would be the bind 
response
packet. Check for the commandstatus field. You can think of using 
DefaultDecomposer
to decompose the fields. If command status is ESME_ROK(0x00) then your bind is
successful.
6) For successful bind, you can start sending the SubmitSM packets to the 
SMSC.You
can think of using the DefaultPDUSender class' sendSubmitSm() to send your 
packets
asynchronously. Keep the sender thread as busy as required to achieve your 
desired
throughput. Keep appropriate values for all the parameters. Keep the short 
message
encoded with the required data coding value. ScheduleDeliveryTime should be 
null for
immediate delivery of message. Keep RegisteredDelivery as
SMSCDeliveryReceipt.SUCCESS_FAILURE if you are want a DR. Please take care of 
the
sequence numbers as they are an integral part in determining the responses from 
the
operator.
7) All your responses would be send back to you which should be collected by 
your
reader thread to the input stream.
8) Most of the real operators keep a socket timeout period(session timeout). It 
is
the maximum idle time that its input stream would wait without reading 
packets(in
most cases 20 secs). So you need to make sure that your application keeps 
sending
packets to the operator's output stream. For this purpose you can think of 
sending
EnquireLink packets to the operator's output stream. Think of running a third 
thread
that would be invoked in every 10 seconds or something which sends EnquireLink 
packet
to the operator if it finds that the last packet was send very early. This 
would also
let you know whether the connection is still active. If you get an IOException, 
it
means your stream got closed. Then you have to stop sending SubmitSM packets to 
the
operator's output stream till you rebind to the SMSC. EnquireLinkResponse is 
also
used by the operator to indicate you special situations using command status. 
You
will have to think of rebinding with the SMSC if the command status is not 
ESME_ROK.
9) When you are done or in Shutdownhook, think of sending the unbind request to 
the
SMSC, sleep for 1000ms or so for the UnbindResponse from SMSC, close the 
streams(i/p
and o/p), close the socket.

Most importantly:

Think of logging all your important requests and responses to analyze it in 
detail
later. The current jsmpp versions do not support toString() for PDU subclasses. 
I
have requested the team for the implementation of toString() in all PDU
subclasses.(issue 68). You can think of using logica smpp api, with PDU class'
debugString() if you feel it difficult to call all the getter methods.

I think that this should help you in implementing your application.
Best of luck!

Original comment by hbkricha...@gmail.com on 7 May 2010 at 4:29

GoogleCodeExporter commented 8 years ago
session timeout i was telling in step 8 is the maximum time that its input 
stream
would wait for reading packets(in most cases 20 secs). This is similar to socket
timeout. Sorry for the mistake.

Original comment by hbkricha...@gmail.com on 7 May 2010 at 5:08

GoogleCodeExporter commented 8 years ago
Socket socket = new Socket(SMSCIp, port);
DefaultPDUSender sender=new DefaultPDUSender();
OutputStream out=socket.getOutputStream();
sender.sendBind(out,BindType.BIND_TX,sequence, systemId,
                password, systemType,
                InterfaceVersion.IF_34,TypeOfNumber.UNKNOWN,
                NumberingPlanIndicator.UNKNOWN, addressRange);
            sender.sendSubmitSm(out,sequence,"CMT",TypeOfNumber.ALPHANUMERIC,     
NumberingPlanIndicator.UNKNOWN,
            source, TypeOfNumber.UNKNOWN,
            NumberingPlanIndicator.UNKNOWN, destination,
            new ESMClass(), (byte) 0, (byte) 1, null, null,
            new RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT),
            (byte) 0, new GeneralDataCoding(false, false,
                    MessageClass.CLASS1, Alphabet.ALPHA_DEFAULT),
            (byte) 0, message.getBytes());
Now i am using DefaultPDUSender class.Can you tell what "Sequence Number" shall 
i
give in the method sendbind() and sendSubmitSM(). i av checked the value 
returned by
socket.getSoTimeout().It gives "0" so my SMSC has i guess no timout value set.

Original comment by farooq.z...@gmail.com on 10 May 2010 at 11:37

GoogleCodeExporter commented 8 years ago
The sequence number should be in ascending order(SEQUENCE). If your bind request
starts with sequence number 1, then the next packet you send should contain 2 
in its
sequence number field.

Most importantly, the sequence number is used to keep track of your responses. 
Assume
that in one bind session you started sending messages. Let your bind request 
start
with seqNum 1. Then it was followed by 10 submitsm with sequence numbers 2-11. 
By
some cause the session was unbound. At that time assume that you received only 5
SubmitSmResp and 5 DeliverSM packets. So when you bind to the operator the next 
time,
you would expect to get 5 more SubmitSmResp and 5 more DeliverSM pdus. The
SubmitSmResp packets would contain the previously submitted sequence numbers. 
So for
the second bind session established it is always good to start Bind Request with
sequence number 12 or different sequence number than the previously established 
ones.
So you should keep track of the last used sequenceNumber(in database/some 
file). It
is enough to keep track of the sequence number of the last send submitSm pdu.

There can be problems at the operator side also if you use same sequence 
numbers for
SubmitSm packets. Some operators might reject the packets. And if you have to 
make
any query with the operator about the status of the submitted short message it 
would
be difficult if you do not have separate sequence numbers.

Please refer to SMPP spec 3.4/5.0 along with your development. It should clear 
most
of your doubts.

Original comment by hbkricha...@gmail.com on 10 May 2010 at 1:54

GoogleCodeExporter commented 8 years ago
hi Mr. farooq.zubairi, hope you are doing fine, am trying to make my 
application send messages asynchronously, and i did as uudashr did in one of 
his examples to use ExecutorService but also in this way we keep blocking the 
messages till we receive a reponse, please refer to issue 89 you can find a 
full explanation of my problem, can you send me sample of your code using 
DefaultPDUSender, to send asynchronously and how to receive the responses back.

your quick response is highly appreciated

regards

Original comment by msy...@gmail.com on 5 Dec 2010 at 1:58

GoogleCodeExporter commented 8 years ago
Hello 

I had a slow response but i the problem was not with the smpp API when ever we 
connect to the Gateway it created a connection sometimes gateway refuse to 
connect to the client my problem was when i connect twise gateway reject and 
application hang out before digging into the detail please find if Gateway has 
enough number of open connections for you.

Original comment by farooq.z...@gmail.com on 7 Dec 2010 at 6:08

GoogleCodeExporter commented 8 years ago
hi,
there is no problem with the gateway, the operator is giving us 4 sessions to 
open on the SMSC, and can reach 200sms/sec, but because am using synchronous 
sending am only able to send 7-10sms/sec/session. but id i used asynchronous i 
can make it to 200sms, my problem is that the blocking when sending and waiting 
for the response.

if you can send me a sample of your code, i would really appreciate it

Original comment by msy...@gmail.com on 7 Dec 2010 at 9:49

GoogleCodeExporter commented 8 years ago
My code is not that complexx 

JSMPPSessionController is singleton class for connection binding and main 
tunning code is following

try 
{

session = JSMPPSessionController.getInstance();
if (session.getSessionState() == SessionState.OPEN)
{
                session.submitShortMessage("CMT", TypeOfNumber.ALPHANUMERIC,
        NumberingPlanIndicator.UNKNOWN, source,
        TypeOfNumber.UNKNOWN, NumberingPlanIndicator.UNKNOWN,
        destination, new ESMClass(), (byte) 0, (byte) 1, null,
        null, new RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT),
        (byte) 0, new GeneralDataCoding(false, false,
        MessageClass.CLASS1, Alphabet.ALPHA_DEFAULT),
        (byte) 0, smsText.getBytes());
    logger.info("Message Sent");
}

}catch (Exception e) 
{
    logger.info(" Error in sending Message Message-Content{Source "
    + source + " Destination " + destination + "  SMS "
    + smsText + "}");
    logger.info(" Exception " + e.getMessage());

    if (session.getSessionState() == SessionState.CLOSED
        || session.getSessionState() == SessionState.UNBOUND) {
    try {
        JSMPPSessionController.bind();
            logger.info(" Successfully Bind Again " );

                } catch (Exception e1) {
                    logger.info(" Failed to Bind in Second Attempt");
                }
            }

        }

I had a problem with slow sms processing but that wass due to Gateway 
connection problems and now it is processing with good amount of transaction 
per seconds in my problem that it was 10 TPS and it serving very well.
This code is running in production from last 6 months and working fine.

Original comment by farooq.z...@gmail.com on 8 Dec 2010 at 6:43

Attachments:

GoogleCodeExporter commented 8 years ago
and how do you keep track of your messages? when you use 
session.submitShortMessage without having message id, what will happen with the 
delivery reports how can you match?

Original comment by msy...@gmail.com on 8 Dec 2010 at 9:15

GoogleCodeExporter commented 8 years ago
Oh right in my problem this was not the case you need confirm delivery of the 
message or you want to perform some other task on delivery

Original comment by farooq.z...@gmail.com on 9 Dec 2010 at 7:33

GoogleCodeExporter commented 8 years ago
kindly plz guide me if i try send sms in bulk it gives error

org.jsmpp.extra.NegativeResponseException: Negative response 0000000d found
    at org.jsmpp.session.AbstractSession.validateResponse(AbstractSession.java:215)
    at org.jsmpp.session.AbstractSession.executeSendCommand(AbstractSession.java:271)
    at org.jsmpp.session.SMPPSession.submitShortMessage(SMPPSession.java:320)

Original comment by faruk.ar...@gmail.com on 24 Mar 2013 at 2:34

Attachments:

GoogleCodeExporter commented 8 years ago
please help me out ov this where m going wrong ??

Original comment by faruk.ar...@gmail.com on 24 Mar 2013 at 2:35

GoogleCodeExporter commented 8 years ago
0x0000000D  ESME_RBINDFAIL  Bind failed

Means, there's something wrong with your connection activity, try to re-check 
your apps and the client side

Original comment by bobbyhar...@gmail.com on 2 Jul 2014 at 11:10