简体   繁体   中英

java.net.SocketException: Broken pipe smpp.logica library

why i got this error

    20:43:40,798 ERROR Tx:809 - java.net.SocketException: Broken pipe
java.net.SocketException: Broken pipe
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
    at com.logica.smpp.TCPIPConnection.send(TCPIPConnection.java:353)
    at com.logica.smpp.Transmitter.send(Transmitter.java:79)
    at com.logica.smpp.Session.send(Session.java:993)
    at com.logica.smpp.Session.send(Session.java:1048)
    at com.logica.smpp.Session.enquireLink(Session.java:789)
    at com.logica.smpp.Tx.kirimEnquireLink(Tx.java:795)
    at com.logica.smpp.Tx.access$0(Tx.java:777)
    at com.logica.smpp.Tx$1.run(Tx.java:120)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)

..I'm Using Open smpp logica library to create smsc client..for a few hours it's work but then the error come out..when i'm trying to send enquiry link,,the session I create is syncronize and the type of connection is Transceiver here's a piece of code i used to bind and to enqury link

   private void bind()
    {
        debug.enter(this, "SMPPTest.bind()");
        try {

            if (bound) {
                System.out.println("Already bound, unbind first.");
                return;
            }

            BindRequest request = null;
            BindResponse response = null;
            String syncMode = (asynchronous ? "a" : "s");

            // type of the session
            syncMode = getParam("Asynchronous/Synchronnous Session? (a/s)",
                                syncMode);
            if (syncMode.compareToIgnoreCase("a")==0) {
                asynchronous = true;
            } else if (syncMode.compareToIgnoreCase("s")==0) {
                asynchronous = false;
            } else {
                System.out.println("Invalid mode async/sync, expected a or s, got "
                                   + syncMode +". Operation canceled.");
                return;
            }

            // input values
            bindOption = getParam("Transmitter/Receiver/Transciever (t/r/tr)",
                                  bindOption);

            if  (bindOption.compareToIgnoreCase("t")==0) {
                request = new BindTransmitter();
            } else if (bindOption.compareToIgnoreCase("r")==0) {
                request = new BindReceiver();
            } else if (bindOption.compareToIgnoreCase("tr")==0) {
                request = new BindTransciever();
            } else {
                System.out.println("Invalid bind mode, expected t, r or tr, got " +
                                   bindOption + ". Operation canceled.");
                return;
            }

            ipAddress = getParam("IP address of SMSC", ipAddress);
            port = getParam("Port number", port);

            TCPIPConnection connection = new TCPIPConnection(ipAddress, port);
            connection.setReceiveTimeout(20*1000);
            session = new Session(connection);

            systemId = getParam("Your system ID", systemId);
            password = getParam("Your password", password);

            // set values
            request.setSystemId(systemId);
            request.setPassword(password);
            request.setSystemType(systemType);
            request.setInterfaceVersion((byte)0x34);
            request.setAddressRange(addressRange);

            // send the request
            System.out.println("Bind request " + request.debugString());
            if (asynchronous) {
                pduListener = new SMPPTestPDUEventListener(session);
                response = session.bind(request,pduListener);
            } else {
                response = session.bind(request);
            }
            System.out.println("Bind response " + response.debugString());
            if (response.getCommandStatus() == Data.ESME_ROK) {
                System.out.println("CommandID "+response.getCommandId());
                bound = true;
            }

        } catch (Exception e) {
            event.write(e,"");
            debug.write("Bind operation failed. " + e);
            System.out.println("Bind operation failed. " + e);
        } finally {
            debug.exit(this);
        }
    }

the code for enquiry link is

 private void kirimEnquireLink()
  {
    try
    {
      log.info("Send enquireLink!");
      EnquireLink request = new EnquireLink();
      EnquireLinkResp response = new EnquireLinkResp();
//      synchronized (session) {
//        session.enquireLink(request);
//      }
      if(asynchronous)
      {
          session.enquireLink(request);
      }else
      {
          response = session.enquireLink(request);
          System.out.println("Enquire Link Response "+request.debugString());
      }

    }
    catch (Exception e)
    {
      bound = false;
    //  unbind();
      log.error(e, e);
    }
  }

i called enquiry link every 10 second,, any idea why

The problem you are facing is that there is never insurance that connection will be always available, nor the session. Many different external reasons can bring the link between ESME and SMSC down. My suggestion, try-catch the enquire_link operations and the submit operations, evaluate the Exception and take action.

I've successfully implemented recursive method calls to deal with this issue as follows

/**
 * Connect to ESME and submit a message, if binding process fails, reattempt
 * to reconnect and submit.
 */
public void connect() {

    try {
        //Create connection
        BindRequest request = null;
        request = new BindTransciever();
        connection = new TCPIPConnection("localhost", 17632);
        connection.setReceiveTimeout(20 * 1000);
        session = new Session(connection);
        //Prepare request
        request.setSystemId("pavel");
        request.setPassword("wpsd");
        request.setSystemType("CMT");
        request.setInterfaceVersion((byte) 0x34);
        request.setAddressRange(new AddressRange());
        pduListener = new SMPPTestPDUEventListener(session);

        //Session binding process, if it fails, we are thrown to the catch section
        //with a BrokenPipe (IOException)
        session.bind(request, pduListener);

        //Prepare message
        SubmitSM msg = new SubmitSM();
        // set values
        msg.setDestAddr("04234143939");
        msg.setShortMessage("hello");
        msg.assignSequenceNumber(true);

        //Send to our custom made submitMessage method that reattempts if failure
        submitMessage(msg);

    } catch (Exception ex){
            //Analyze what type of exception was
            if (ex instanceof IOException || ex instanceof SocketException){
                //IOException relate to the brokenpipe issue you are facing
                //you need to close existing sessions and connections
                //restablish session
                if (this.connection!=null){
                    this.connection.close();
                }
                //This is a recursive call, I encourage you to elaborate
                //a little bit this method implementing a counter so you
                //don't end up in an infinite loop
                this.connect();
            } else {
                //LOG whatever other exception thrown
            } 
    }
}

    /**
 * Submit message to SMSC, if it fails because of a connection issue, reattempt
 * @param message 
 */
private void submitMessage(SubmitSM message){
        try{
            session.submit(message);
        } catch (Exception ex){
            //Analyze what type of exception was
            if (ex instanceof IOException || ex instanceof SocketException){
                //IOException relate to the brokenpipe issue you are facing
                //you need to close existing sessions and connections
                //restablish session and try to submit again
                if (this.connection!=null){
                    this.connection.close();
                }
                //Call a rebind method
                this.bind();
                //This is a recursive call, I encourage you to elaborate
                //a little bit this method implementing a counter so you
                //don't end up in an infinite loop
                this.submitMessage(message);
            } else {
                //LOG whatever other exception thrown
            }
        }
}

Do the same with the enquire_link, try-catch, during IOException rebind, and reattempt. Do not forget to add a couter and a maximum ammount of attempts in order to avoid infinite loops during recursive calls.

You do not need to enquire_link every 10 seconds. Most providers will let you know how often it needs to be done, the standard is 10 minutes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM