将 iOS 应用程序连接到托管在亚马逊上的 Ejabberd 服务器

Connecting iOS app to Ejabberd Server hosted on Amazon

我在 Amazon 上托管了 Ejabberd 聊天服务器并在那里添加了两个用户,当我尝试通过 Adium 连接 Ejabberd 服务器时,它要求证书然后只有它连接,现在我是使用 Ejabberd 服务器和 XMPP 在 Swift 中开发聊天应用程序,我配置了所有代码,传递了主机名和端口号:5222,但它没有连接到服务器。 我是否需要编写程序来获取服务器证书并将我的计算机证书 (.p12) 文件传递​​给服务器?

注意:我在本地主机中配置了 Ejabberd 服务器并通过 iOS Swift 代码,当我从 iOS 发送消息时它工作正常应用程序然后它显示在 Adium 中,当 Adium 用户发送消息时,我转到 Ejabberd Web 管理面板并可以检查离线消息。

这是 Swift 中用于连接亚马逊托管的 Ejabberd 的代码:

//
//  AppDelegate.swift
//  Thanks to Process One for this.

import UIKit
import XMPPFramework

protocol ChatDelegate {
    func buddyWentOnline(_ name: String)
    func buddyWentOffline(_ name: String)
    func didDisconnect()
}

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, XMPPRosterDelegate, XMPPStreamDelegate {

    var window: UIWindow?
    var delegate:ChatDelegate! = nil
    let xmppStream = XMPPStream()
    let xmppRosterStorage = XMPPRosterCoreDataStorage()
    var xmppRoster: XMPPRoster

    override init() {
        xmppRoster = XMPPRoster(rosterStorage: xmppRosterStorage)
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        DDLog.add(DDTTYLogger.sharedInstance())

        setupStream()

        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
        disconnect()
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        connect()
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

    //MARK: Private Methods
     func setupStream() {//fileprivate
        //xmppRoster = XMPPRoster(rosterStorage: xmppRosterStorage)
        xmppRoster.activate(xmppStream)
        xmppStream?.addDelegate(self, delegateQueue: DispatchQueue.main)
        xmppRoster.addDelegate(self, delegateQueue: DispatchQueue.main)
    }

     func goOnline() { //fileprivate
        let presence = XMPPPresence()
        let domain = xmppStream?.myJID.domain

        if domain == "gmail.com" || domain == "gtalk.com" || domain == "talk.google.com" {
            let priority = DDXMLElement.element(withName: "priority", stringValue: "24") as! DDXMLElement
            presence?.addChild(priority)
        }

        xmppStream?.send(presence)
    }

     func goOffline() { //fileprivate
        let presence = XMPPPresence(type: "unavailable")
        xmppStream?.send(presence)
    }

    func connect() -> Bool {
        xmppStream.hostName = "amazon hosted ejabber ip address"
        xmppStream.hostPort=5222
        if !(xmppStream?.isConnected())! {
            let jabberID = UserDefaults.standard.string(forKey: "userID")
            let myPassword = UserDefaults.standard.string(forKey: "userPassword")

            if !(xmppStream?.isDisconnected())! {
                return true
            }
            if jabberID == nil && myPassword == nil {
                return false
            }


            xmppStream?.myJID = XMPPJID.init(string: jabberID)

            do {
                try xmppStream?.connect(withTimeout: XMPPStreamTimeoutNone)
                print("Connection success")
                return true
            } catch {
                print("Something went wrong!")
                return false
            }
        } else {
            return true
        }
    }

    func disconnect() {
        goOffline()
        xmppStream?.disconnect()
    }

    //MARK: XMPP Delegates
    func xmppStreamDidConnect(_ sender: XMPPStream!) {
        do {
            try xmppStream?.authenticate(withPassword: UserDefaults.standard.string(forKey: "userPassword"))
        } catch {
            print("Could not authenticate")
        }
    }

    func xmppStreamDidAuthenticate(_ sender: XMPPStream!) {
        goOnline()
    }

    func xmppStream(_ sender: XMPPStream!, didReceive iq: XMPPIQ!) -> Bool {
        print("Did receive IQ")
        return false
    }

    func xmppStream(_ sender: XMPPStream!, didReceive message: XMPPMessage!) {
        print("Did receive message \(message)")
    }

    func xmppStream(_ sender: XMPPStream!, didSend message: XMPPMessage!) {
        print("Did send message \(message)")
    }

    func xmppStream(_ sender: XMPPStream!, didReceive presence: XMPPPresence!) {
        let presenceType = presence.type()
        let myUsername = sender.myJID.user
        let presenceFromUser = presence.from().user

        if presenceFromUser != myUsername {
            print("Did receive presence from \(presenceFromUser)")
            if presenceType == "available" {
                delegate.buddyWentOnline("\(presenceFromUser)@gmail.com")
            } else if presenceType == "unavailable" {
                delegate.buddyWentOffline("\(presenceFromUser)@gmail.com")
            }
        }
    }

    func xmppRoster(_ sender: XMPPRoster!, didReceiveRosterItem item: DDXMLElement!) {
        print("Did receive Roster item")
    }
}

最后我设法解决了这个问题,我真的很惊讶使用亚马逊上托管的 Ejabberd 服务器实现聊天应用程序。

问题:

1. 当我 运行 连接我的应用程序时,它没有连接?

答案:证书问题(服务器-客户端证书握手解决问题)

2. 无法获取在线好友? 回答:我使用 Adium 让所有用户在线,然后 运行 我的应用程序,它就像一个魅力。

这个应用程序对我来说是很好的学习。 如果任何人对聊天有任何问题,请随时发表评论,我期待着帮助。谢谢