1. 程式人生 > >openfire+smack4.2.2構建即時通訊應用遇到的各種坑

openfire+smack4.2.2構建即時通訊應用遇到的各種坑

第一次寫部落格。

發現在搭建伺服器,寫程式碼的過程中等過程中,遇到了許多坑,費了許多時間。如果不記下來,會忘記許多。

正好現在新版smack的資料比較少,查的可費勁了還查不到需要的。

分享給大家。

首先,回顧下流程。

在官網下載openfire,spark,smack。openfire是開源的伺服器,安裝以後,搭建自己的伺服器。具體步驟網上可以搜到。一般是正確的。在此,提兩點,域名可以自己設定成自己想要的。域名就是指向本機外網IP的一個名字。本機IP可以通過cmd命令列,輸入ipconfig來查詢(ipv4對應的)。另外,連線資料庫我是下載的MYSQL資料庫。MYSQL資料庫安裝的時候,只安裝server就可以。安裝完了,用navicat工具開啟mysql。新建一個數據庫openfire(自己取名字),然後執行sql檔案,找openfire目錄下的openfire_mysql.sql。如圖:

 

執行完了,就可以得到圖中的那些表。

spark是客戶端,可以通過它,登入自己的伺服器。用來測試伺服器能不能用的。這裡有個問題就是域填什麼。最開始看到真是感覺坑爹。最後發現是填伺服器名,也就是上面提到的域名。

smack解壓出來,是各種jar包,匯入需要的到lib中並新增依賴關係。當然還有其他的jar包。如圖:

 

前戲終於搞完了,可以寫程式碼了。

然後我就卡在了連線伺服器上面。由於最新版的smack又許多更新,以前的登入程式碼不能用了。官網呢,也不好查。找了半天,新版的是這樣連線的。

public void run() {
    try {
        String server="xxxx"; \\xxxx代表本機

IP,前面提到的。
        InetAddress addr = InetAddress.getByName("xxxx);
        XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                .setUsernameAndPassword("admin","xxx") \\ 自己在伺服器上設定的賬號

.setHost(server) //it will be resolved by setHostAddress method
                .setPort(5222)
                .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setDebuggerEnabled(true)
                .build();
        conn = new XMPPTCPConnection(config);

        conn.connect();
        conn.login();
        if(conn.isConnected()){
            Log.d("XMPP","Connected");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

出現瞭如圖的錯誤:

沒定義XMPP domaindomain是域名的意思。那就設定個域名吧。誒,域名不就是我前面說的那個自己設定的域名嗎?不好意思,不是。似乎以前可以,現版本不是的,這也是坑了我不少時間的坑。不廢話了,全部給出。如下

加上:

InetAddress addr = InetAddress.getByName("xxxx");
HostnameVerifier verifier = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return false;
    }
};

DomainBareJid serviceName = JidCreate.domainBareFrom("xxxx");

.setXmppDomain(serviceName)//加在config下面的屬性中。

.setServiceName(serviceName)

.setHostnameVerifier(verifier)
.setHostAddress(addr)

Ok.終於可以連線上了!

看似簡單,但實際上卡了我許久。因為百度和谷歌都難以查到。

接下來,本文最後提到的一個坑點,也是卡我時間最長的。

登入寫完了,那咱是不是得寫註冊啊。

思路是將連線openfire的程式碼寫在一個服務中,然後,註冊和登入的Activity分開。

看起來很簡單。

繼續寫註冊的唄。

public void onClick(View v) {
    conn1=binder.getAbstractXMPPConnection();
    AccountManager manager = AccountManager.getInstance(conn1);
    manager.sensitiveOperationOverInsecureConnection(true);//不加會報錯,敏感操作。
    try {
        manager.createAccount(Localpart.from("fuck"),"123");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Conn1是從服務中獲得的連線。

依然報錯:

com.xzq.textofim W/System.err: org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPP error reply received from xxxx. XMPPError: bad-request - modify

xxxx是本機IP,我匿了。

誒,臥槽。沒毛病啊,不就是這麼弄的嗎。邏輯上沒有問題啊。我查了許久,有說沒設定ServiceName的,或者ServiceName不能從localhost(127.0.0.1)上得的。但是都沒有解決問題。依然是註冊不了,依然是這個報錯。

本來我是寫在一個有UI裡的,但是實在不知道哪錯了。

心灰意冷之下,新開工程,把核心連線登入註冊的程式碼直接擼上。使用者名稱密碼不再是自己在手機或者模擬器上輸入的了(也就是本文給出的程式碼)。

無意中嘗試,終於得到答案。這特麼的也太噁心了。

註冊居然需要先登入,才能註冊。

也就是說,必須在註冊之前,先進行登入。這坑爹的邏輯。所以,在註冊的Activity中,先進行登入。然後再註冊。

成功了。當然還有些問題就是,登入完了以後,必須得退出登入。然後回到登入的Activity中,才能用註冊的賬號登入。

這之中還有些坑,暫且不表,可以不管,繼續後面的內容。

第一次寫部落格,希望我寫的內容能對大家有些幫助!