【问题标题】:xmpp connection blackberry javaxmpp连接黑莓java
【发布时间】:2026-02-01 20:25:02
【问题描述】:

我能够连接 xmpp 服务器并完成登录身份验证,但是当我发送名册时,输入流 is.read() 给了我 -1 并抛出了一个异常,我现在不知道该怎么办。请帮帮我。

我的 XMppCONnection 类:

package mypackage;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;

import javax.microedition.io.ConnectionNotFoundException
 import javax.microedition.io.SecureConnection;
 import javax.microedition.io.StreamConnection;
import net.rim.device.api.io.File;
import net.rim.device.api.io.FileInputStream;
import net.rim.device.api.io.FileOutputStream;


public class XMPPConnection extends XMPPThread {

private XmlReader reader;
private XmlWriter writer;
private InputStream is;
private OutputStream os;
      FileInputStream fis;
    FileOutputStream fos;
   File file;
/**
 * If you create this object all variables will be saved and the
 * method {@link #run()} is started to log in on jabber server and
 * listen to parse incomming xml stanzas. Use
 * {@link #addListener(XmppListener xl)} to listen to events of this object.
 */

// jid must in the form "username@host"
// to login Google Talk, set port to 5223 (NOT 5222 in their offical guide) 
public XMPPConnection(Connection connection) {
    super(connection);

    this.host = connection.getHost();
    this.port = connection.getPort();
    this.username = connection.getUsername();
    this.password = connection.getPassword();
    this.resource = "mobile";
    this.myjid = this.username + "@" + this.host;
    if (connection.getServer() == null)
        this.server = host;
    else
        this.server = connection.getServer();
    this.use_ssl = connection.isSSL();
    this.connectionMaskIndex = connection.getNetworkType();
}

/**
 * The <code>run</code> method is called when {@link XMPPConnection} object is
 * created. It sets up the reader and writer, calls {@link #login()}
 * methode and listens on the reader to parse incomming xml stanzas.
 */
public void run() {     
    try {
        this.connect();
    } catch (final IOException e) {
        e.printStackTrace();
        this.connectionFailed(e.getMessage());
        return;
    } catch (Exception e) {
        e.printStackTrace();
        this.connectionFailed(e.getMessage());
        return;
    }

    // connected
    try {
        boolean loginSuccess = this.login();
        if (loginSuccess) {
            this.parse();

        }           
    } catch (final Exception e) {
        // hier entsteht der connection failed bug (Network Down)
        java.lang.System.out.println(e);
        this.connectionFailed(e.toString());
    }
}


protected void connect() throws IOException, Exception {
    if (!use_ssl) {         
        //final StreamConnection connection = (StreamConnection) Connector.open("http://" + this.server + ":" + this.port+this.connectionMask, Connector.READ_WRITE);
        ConnectionFactory connectionFactory = new ConnectionFactory("socket://" + this.server + ":" + this.port, this.connectionMaskIndex);
        StreamConnection connection = null;

        try {
            connection = (StreamConnection) connectionFactory.getNextConnection();


        } catch (NoMoreTransportsException e) {
            throw new Exception("Connection failed. No transport available.");

        } catch (ConnectionNotFoundException e) {
            throw new Exception("ConnectionNotFoundException:" + e.getMessage());

        } catch (IllegalArgumentException e) {
            throw new Exception("IllegalArgumentException: " + e.getMessage());

        } catch (IOException e) {
            throw new Exception("IOException: " + e.getMessage());

        }

        is = connection.openInputStream();
        os = connection.openOutputStream();

        this.reader = new XmlReader(is);
        this.writer = new XmlWriter(os);

    } else {
        //final SecureConnection sc = (SecureConnection) Connector.open("ssl://" + this.server + ":" + this.port+this.connectionMask, Connector.READ_WRITE);
        ConnectionFactory connectionFactory = new ConnectionFactory("ssl://" + this.server + ":" + this.port, this.connectionMaskIndex);
        SecureConnection sc = null;
        try {
            sc = (SecureConnection) connectionFactory.getNextConnection();

        } catch (NoMoreTransportsException e) {
            throw new Exception("Connection failed. No transport available.");

        } catch (ConnectionNotFoundException e) {
            throw new Exception("ConnectionNotFoundException: " + e.getMessage());

        } catch (IllegalArgumentException e) {
            throw new Exception("IllegalArgumentException: " + e.getMessage());

        } catch (IOException e) {
            throw new Exception("IOException: " + e.getMessage());

        }

        if (sc != null) {
            //sc.setSocketOption(SocketConnection.DELAY, 1);
            //sc.setSocketOption(SocketConnection.LINGER, 0);
            is = sc.openInputStream();
            os = sc.openOutputStream();
            this.reader = new XmlReader(is);
            this.writer = new XmlWriter(os);
        }

    }
}

/**
 * Opens the connection with a stream-tag, queries authentication type and
 * sends authentication data, which is username, password and resource.
 * @return 
 * @throws Exception 
 */
protected boolean login() throws Exception {
    String msg = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" + this.host + "' version='1.0'>";
    os.write(msg.getBytes());
    os.flush();


    do {

        reader.next();
        if (reader.getType() == XmlReader.START_TAG && reader.getName().equals("stream:features")) {
            this.packetParser.parseFeatures(reader);
        }               
    } while (!(reader.getType() == XmlReader.END_TAG && reader.getName().equals("stream:features")));


    boolean loginSuccess = this.doAuthentication();


    msg = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" + this.host + "' version='1.0'>";
    os.write(msg.getBytes());
    os.flush();
    reader.next();
    while (true) {
        if ((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("stream:features")) {
            break;
        }
        reader.next();
    }


    if (resource == null) {
        msg = "<iq type='set' id='res_binding'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
    } else {
        msg = "<iq type='set' id='res_binding'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>" + resource + "</resource></bind></iq>";
    }
    os.write(msg.getBytes());
    os.flush();

    return loginSuccess;
}



protected void parse() throws IOException {
    while (true) {
        int nextTag = this.reader.next();
        switch (nextTag) {
        case XmlReader.START_TAG:
            final String tmp = this.reader.getName();
            if (tmp.equals("message")) {
                this.packetParser.parseMessage(this.reader);
            } else if (tmp.equals("presence")) {
                this.packetParser.parsePresence(this.reader);
            } else if (tmp.equals("iq")) {
                this.packetParser.parseIq(this.reader, this.writer);
            } else {
                this.packetParser.parseIgnore(this.reader);
            }
            break;

        case XmlReader.END_TAG:
            this.reader.close();
            throw new IOException("Unexpected END_TAG "+this.reader.getName());

        default:
            this.reader.close();
            throw new IOException("Bad XML tag");
        }
    }
}


protected boolean doAuthentication() throws Exception {
    boolean loginSuccess = false;

    Vector mechanismList = this.packetParser.getMechanism();
     System.out.println(mechanismList.toString());
    if (mechanismList.contains("X-GOOGLE-TOKEN")) {
        // X-GOOGLE-TOKEN authorization doing. User can disable
        // google features using by deselecting corresponding
        // checkbox in profile
        String resp = this.packetParser.getGoogleToken(this.myjid, this.password);

        String msg = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-GOOGLE-TOKEN\">" + resp + "</auth>";
        os.write(msg.getBytes());
        //os.flush();       

        reader.next();
        if (reader.getName().equals("success")) {
            loginSuccess = true;
            while (true) {
                if ((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("success")) {
                    break;
                }
                reader.next();
            }
        }
    }       


    if (mechanismList.contains("PLAIN") && loginSuccess == false) {
        String msg = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>";
        byte[] auth_msg = (username + "@" + host + "\0" + username + "\0" + password).getBytes();
        msg = msg + MD5.toBase64(auth_msg) + "</auth>";
        os.write(msg.getBytes());
        os.flush();
        reader.next();
        if (reader.getName().equals("success")) {
            loginSuccess = true;
            while (true) {
                if ((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("success")) {
                    break;
                }
                reader.next();
            }
        }
    }

    if (loginSuccess == false) {
        for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
            XmppListener xl = (XmppListener) e.nextElement();
            xl.onAuthFailed(reader.getName() + ", failed authentication");
        }
        return false;
    }

    return loginSuccess;
}














public void getRosterVCard(String tojid) throws IOException {
    this.writer.startTag("iq");
    this.writer.attribute("id", "vc2");
    this.writer.attribute("to", tojid);
    this.writer.attribute("type", "get");
    this.writer.startTag("vCard");
    this.writer.attribute("xmlns", "vcard-temp");
    this.writer.endTag(); // vCard
    this.writer.endTag(); // iq
    this.writer.flush();
}


/**
 * Sends a roster query.
 * 
 * @throws java.io.IOException is thrown if {@link XmlReader} or {@link XmlWriter}
 *  throw an IOException.
 */
public void getRoster() throws IOException {



    this.writer.startTag("iq");
   //       this.writer.attribute("id", "roster");

    this.writer.attribute("type", "get");
    this.writer.startTag("query");
    this.writer.attribute("xmlns", "jabber:iq:roster");
    this.writer.endTag(); // query
    this.writer.endTag(); // iq
    this.writer.flush();

    //<iq id="qxmpp7" from="919700424402@213.204.83.20/QXmpp" type="get"><query xmlns="jabber:iq:roster"/></iq>

}   

/**
 * Sends a message text to a known jid.
 * 
 * @param to the JID of the recipient
 * @param msg the message itself
 */
public void sendMessage(final String to, final String msg, final String id) {
    try {
        this.writer.startTag("message");
        this.writer.attribute("type", "chat");
        this.writer.attribute("to", to);
        this.writer.startTag("body");
        this.writer.text(msg);
        this.writer.endTag();
        this.writer.endTag();
        this.writer.flush();
    } catch (final IOException e) {
        java.lang.System.out.println(e);
        this.connectionFailed();
    }
}

/**
 * Requesting a subscription.
 * 
 * @param to the jid you want to subscribe
 */
public void subscribe(final String to) {
    this.sendPresence(to, "subscribe", null, null, 0);
}

/**
 * Remove a subscription.
 * 
 * @param to the jid you want to remove your subscription
 */
public void unsubscribe(final String to) {
    this.sendPresence(to, "unsubscribe", null, null, 0);
}

/**
 * Approve a subscription request.
 * 
 * @param to the jid that sent you a subscription request
 */
public void subscribed(final String to) {
    this.sendPresence(to, "subscribed", null, null, 0);
}

/**
 * Refuse/Reject a subscription request.
 * 
 * @param to the jid that sent you a subscription request
 */
public void unsubscribed(final String to) {
    this.sendPresence(to, "unsubscribed", null, null, 0);
}   

/**
 * Sets your Jabber Status.
 * 
 * @param show is one of the following: <code>null</code>, chat, away,
 *        dnd, xa, invisible
 * @param status an extended text describing the actual status
 * @param priority the priority number (5 should be default)
 */
public void setStatus(String show, String status, final int priority) {
    if (show.equals("")) {
        show = null;
    }
    if (status.equals("")) {
        status = null;
    }
    if (show.equals("invisible")) {
        this.sendPresence(null, "invisible", null, null, priority);
    } else {
        this.sendPresence(null, null, show, status, priority);
    }
}

/**
 * Sends a presence stanza to a jid. This method can do various task but
 * it's private, please use setStatus to set your status or explicit
 * subscription methods subscribe, unsubscribe, subscribed and
 * unsubscribed to change subscriptions.
 */
public void sendPresence(final String to, final String type, final String show, final String status, final int priority) {
    try {
        this.writer.startTag("presence");
        if (type != null) {
            this.writer.attribute("type", type);
        }
        if (to != null) {
            this.writer.attribute("to", to);
        }
        if (show != null) {
            this.writer.startTag("show");
            this.writer.text(show);
            this.writer.endTag();
        }
        if (status != null) {
            this.writer.startTag("status");
            this.writer.text(status);
            this.writer.endTag();
        }
        if (priority != 0) {

            this.writer.startTag("priority");
            this.writer.text(Integer.toString(priority));
            this.writer.endTag();
            }


        this.writer.endTag(); // presence
        this.writer.flush();
    } catch (final IOException e) {
        java.lang.System.out.println(e);
        this.connectionFailed();
    }
}

/**
 * Closes the stream-tag and the {@link XmlWriter}.
 */
public void logoff() {
    try {
        this.writer.endTag();
        this.writer.flush();
        this.writer.close();
    } catch (final IOException e) {
        java.lang.System.out.println(e);
        this.connectionFailed();
    }
}







/**
 * Save a contact to roster. This means, a message is send to jabber
 * server (which hosts your roster) to update the roster.
 * 
 * @param jid the jid of the contact
 * @param name the nickname of the contact
 * @param group the group of the contact
 * @param subscription the subscription of the contact
 */
public void saveContact(final String jid, final String name, final Enumeration group, final String subscription) {
    try {
        this.writer.startTag("iq");
        this.writer.attribute("type", "set");
        this.writer.startTag("query");
        this.writer.attribute("xmlns", "jabber:iq:roster");
        this.writer.startTag("item");
        this.writer.attribute("jid", jid);
        if (name != null) {
            this.writer.attribute("name", name);
        }
        if (subscription != null) {
            this.writer.attribute("subscription", subscription);
        }
        if (group != null) {
            while (group.hasMoreElements()) {
                this.writer.startTag("group");
                this.writer.text((String) group.nextElement());
                this.writer.endTag(); // group
            }
        }
        this.writer.endTag(); // item
        this.writer.endTag(); // query
        this.writer.endTag(); // iq
        this.writer.flush();
    } catch (final IOException e) {
        java.lang.System.out.println(e);
        this.connectionFailed();
    }
}

















/**
 * This method is used to be called on a parser or a connection error.
 * It tries to close the XML-Reader and XML-Writer one last time.
 *
 */
private void connectionFailed() {
    if (this.writer != null)
        this.writer.close();

    if (this.reader != null)
        this.reader.close();

    for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
        XmppListener xl = (XmppListener) e.nextElement();
        xl.onConnFailed("");
    }
}

private void connectionFailed(final String msg) {
    if (this.writer != null)
        this.writer.close();

    if (this.reader != null)
        this.reader.close();

    for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
        XmppListener xl = (XmppListener) e.nextElement();
        xl.onConnFailed(msg);
    }
}

};

xml 阅读器如下所示:

   public class XmlReader { 
private InputStream is;

public final static int START_DOCUMENT = 0;

public final static int END_DOCUMENT = 1;

public final static int START_TAG = 2;

public final static int END_TAG = 3;

public final static int TEXT = 4;

//private Stack tags;

private boolean inside_tag;

private boolean left_angle;

private String tagName;

private String text;

private final Hashtable attributes = new Hashtable();

private int c;

private int type = START_DOCUMENT;

//public XmlReader(final InputStream in) throws IOException, UnsupportedEncodingException {
public XmlReader(final InputStream in) throws IOException {
    //reader = new InputStreamReader(in, "UTF-8");
    this.is = in;
    //this.tags = new Stack();
    this.inside_tag = false;
    this.left_angle = false;
}

//http://discussion.forum.nokia.com/forum/showthread.php?t=76814
//by abirr
private int getNextCharacter() throws IOException {
    int a = is.read();

    int t=a;

    if((t|0xC0)==t){
        int b = is.read();

        if( b == 0xFF ){ // Check if legal
            t=-1;
        }else if( b < 0x80 ){ // Check for UTF8 compliancy
            throw new IOException("Bad UTF-8 Encoding encountered");

        }else if((t|0xE0)==t) {
            int c = is.read();
            if( c == 0xFF ){ // Check if legal
                t=-1;
            }else if( c < 0x80 ){ // Check for UTF8 compliancy
                throw new IOException("Bad UTF-8 Encoding encountered");
            }else
                t=((a & 0x0F)<<12) | ((b & 0x3F)<<6) | (c & 0x3F);
        }else
            t=((a & 0x1F)<<6)|(b&0x3F);

    }

    return a;

}

public void close() {
    if (is != null) {
        try {
            is.close();
            is = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        /*try {
            reader.close();
        } catch (IOException e) {}*/
    }       
}

public int next() throws IOException {
  /*        while (!this.ready())
        try { 
            java.lang.Thread.sleep(100);
        } catch (InterruptedException e) {}*/

    this.c = getNextCharacter();
    if (this.c <= ' ') {
        while (((this.c = getNextCharacter()) <= ' ') && (this.c != -1)) {
            ;
        }
    }
    if (this.c == -1) {
        this.type = END_DOCUMENT;
        return this.type;
    }

    if (this.left_angle || (this.c == '<')) {
        this.inside_tag = true;
        // reset all
        this.tagName = null;
        this.text = null;
        this.attributes.clear();

        if (this.c == '<') {
            this.left_angle = true;
            this.c = getNextCharacter();
        }
        if (this.left_angle && this.c == '/') {
            this.left_angle = false;
            this.type = END_TAG;
            this.c = getNextCharacter();
            this.tagName = this.readName('>');
        } else if (this.left_angle && ((this.c == '?') || (this.c == '!'))) {// ignore xml heading & // comments
            this.left_angle = false;
            while ((this.c = getNextCharacter()) != '>') {
                ;
            }
            this.next();
        } else {
            this.left_angle = false;
            this.type = START_TAG;
            this.tagName = this.readName(' ');

            String attribute = "";
            String value = "";
            while (this.c == ' ') {
                /*this.c = getNextCharacter();
                attribute = this.readName('=');

                int quote = getNextCharacter();//this.c = this.read(); // '''
                BTalk.debugConsole.addDebugMsg("quote: " + quote);
                this.c = getNextCharacter();
                value = this.readText(quote); //change from value = this.readText(''');
                this.c = getNextCharacter();
                this.attributes.put(attribute, value);
                BTalk.debugConsole.addDebugMsg("attributes: " + attributes);*/



                this.c = getNextCharacter();
                attribute = this.readName('=').trim();                  

                int quote = getNextCharacter();//this.c = this.read(); // '''
                if (quote == 32) {
                    while (quote == 32) {
                        quote = getNextCharacter();//this.c = this.read(); // '''

                    }
                    this.c = getNextCharacter();
                    value = this.readText(quote); //change from value = this.readText(''');
                    this.c = getNextCharacter();
                    this.attributes.put(attribute, value);  

                } else {
                    this.c = getNextCharacter();
                    value = this.readText(quote); //change from value = this.readText(''');
                    this.c = getNextCharacter();
                    this.attributes.put(attribute, value);  
                }

            }
            if (this.c != '/') {
                this.inside_tag = false;
            }
        }
    } else if ((this.c == '>') && this.inside_tag) // last tag ended
    {
        this.type = END_TAG;
        this.inside_tag = false;
    } else {
        this.tagName = null;
        this.attributes.clear();

        this.type = TEXT;
        this.text = this.readText('<');
        // fix the < dismatching problem
        this.left_angle = true;
    }

    return this.type;
}

// NOTICE: this is only for debug use
public void parseHtml() throws IOException {
    while (true) {
        char c;
        c = (char) this.getNextCharacter();
        System.out.print(c);
    }
}

public int getType() {
    return this.type;
}

public String getName() {
    return this.tagName;
}

public String getAttribute(final String name) {
    return (String) this.attributes.get(name);
}

public Enumeration getAttributes() {
    return this.attributes.keys();
}

public String getText() {
    return this.text;
}

private String readText(final int end) throws IOException {
    final StringBuffer output = new StringBuffer("");
    while (this.c != end) {
        if (this.c == '&') {
            this.c = getNextCharacter();
            switch (this.c) {
                case 'l':
                    output.append('<');
                    break;
                case 'g':
                    output.append('>');
                    break;
                case 'a':
                    if (getNextCharacter() == 'm') {
                        output.append('&');
                    } else {
                        output.append('\'');
                    }
                    break;
                case 'q':
                    output.append('"');
                    break;
                case 'n':
                    output.append(' ');
                    break;
                default:
                    output.append('?');
            }

            while ((this.c = getNextCharacter()) != ';') {
                ;
            }
        // NOTICE: Comment out these mystical codes
//          } else if (this.c == '\\') {
//              // NOTICE: What this means?
//              if ((this.c = getNextCharacter()) == '<') {
//                  output.append('\\');
//                  break;
//              } else {
//                  output.append((char) this.c);
//              }
        } else {
            output.append((char) this.c);
        }
        this.c = getNextCharacter();
    }
    // while((c = read()) != end);
    System.out.println(output.toString()+"");
    return output.toString();
}

private String readName(final int end) throws IOException {
    final StringBuffer output = new StringBuffer("");
    do {
        output.append((char) this.c);
    } while (((this.c = getNextCharacter()) != end) && (this.c != '>') && (this.c != '/'));
    return output.toString();
}

};

【问题讨论】:

  • 谁能帮帮我

标签: java exception blackberry xmpp


【解决方案1】:

问题在于会话我们需要在名册之前创建会话

    String msg = "<iq type=\"set\" id=\"session_1\"><session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/></iq>";

    try {
        os.write(msg.getBytes());
        os.flush();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        reader.next();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    if (reader.getName().equals("iq")) {

        while (true) {

                if((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("iq"))
                {
                    session=true;
                    break;
                }


            try {
                reader.next();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    //
now the problem is solved.thank you

【讨论】:

  • 问题已解决。以上是我错过的代码。这在库中不可用。