为啥 XMPPFramework 会阻塞?
Posted
技术标签:
【中文标题】为啥 XMPPFramework 会阻塞?【英文标题】:Why is XMPPFramework blocking?为什么 XMPPFramework 会阻塞? 【发布时间】:2017-06-30 15:29:32 【问题描述】:我们正在尝试获取 XMPPFramework 运行的最小示例。
考虑这个简单的类:
import Foundation
import XMPPFramework
class Connection: NSObject, XMPPStreamDelegate
let stream: XMPPStream
override init()
self.stream = XMPPStream()!
func connectToServer(timeout: TimeInterval)
stream.addDelegate(self, delegateQueue: DispatchQueue.main)
stream.myJID = XMPPJID(string: "myuser")
stream.hostName = "myserver.tld"
stream.hostPort = 5222
do
try stream.connect(withTimeout: timeout)
catch
print(error)
func xmppStreamWillConnect(_ sender: XMPPStream!)
print("will connect")
func xmppStreamDidConnect(_ sender: XMPPStream!)
print("did connect")
self.stream.disconnect()
还有这个简单的测试类:
import Foundation
import XCTest
@testable import MyModule
class ConnectionTests: XCTestCase
func testConnect()
let connection = Connection()
print("Try to connect")
let expectation = self.expectation(description: "connect")
connection.connectToServer(timeout: 3)
self.waitForExpectations(timeout: 5)
我期望这个输出:
Try to connect
will connect
did connect
<5s timeout since I don't fulfill>
如果我的 XMPP 服务器不小心对我的请求做出了积极响应,我希望看到:
Try to connect
will connect
<some error message>
如果 XMPP 服务器没有(快速)回复,我希望:
Try to connect
will connect
<3s timeout reached>
但是,我没有得到这些,而是:
Try to connect
will connect
<5s timeout since I don't fulfill>
发生了什么事?
这是我收集的。
XCTest 等待DispatchQueue.main
。
我们可以控制代表的运行位置;使用DispatchQueue.main
或DispatchQueue(label: "test", qos: .userInitiated, attributes: .concurrent)
似乎并不重要。
我可以在XMPPStream.connectWithTimeout
中跟踪直到dispatch_sync(xmppQueue, block);
的执行,其中xmppQueue
是一个带有标签xmpp
的新队列;该块似乎也已完全执行。
所以我不明白谁在这里阻止了谁,以及如何防止它发生。
【问题讨论】:
不进行身份验证连接的目的是什么?连接后需要登录,否则会关闭连接。 由于xmppStreamDidConnect
没有被调用,我们甚至没有走到那一步。
【参考方案1】:
问题有三个方面:
-
期望超时,因为它从未实现。
我们从来没有看到“确实连接”,因为它从来没有走到那一步。
我们对 XMPP(Framework) 的了解不够,无法理解在哪里插入。
我们实现了一些额外的委托方法:
func xmppStream(_ sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!)
print("socket did connect")
func xmppStreamDidStartNegotiation(_ sender: XMPPStream!)
print("negotiation started")
...
func xmppStream(_ sender: XMPPStream!, didReceiveError error: DDXMLElement!)
print("error: \(error)")
func xmppStreamDidDisconnect(_ sender: XMPPStream!, withError error: Error!)
print("disconnected")
self.afterConnection()
这里,self.afterConnection
是作为附加参数传递给connectToServer
的函数。
我们在测试中改变:
connection.connectToServer(timeout: 3, then: expectation.fulfill() )
现在测试以有序的方式结束,输出如下:
Try to connect
will connect
socket did connect
negotiation started
disconnected
error: Optional(<stream:error xmlns:stream="http://etherx.jabber.org/streams"><host-unknown xmlns="urn:ietf:params:xml:ns:xmpp-streams"/></stream:error>)
毕竟这是服务器的问题。我们需要实施正确的代表来诊断问题;我们本来希望stream.connect
在这种情况下抛出错误!
【讨论】:
【参考方案2】:按如下方式制作该类的单例:
static let sharedInstance = Connection();
现在这样称呼它:
func testConnect()
Connection.sharedInstance.connectToServer(timeout: 3);
【讨论】:
以上是关于为啥 XMPPFramework 会阻塞?的主要内容,如果未能解决你的问题,请参考以下文章