我正在尝试为 XMPP 编写套接字,建立连接后,套接字应使用更新的 TLS 设置重新建立连接。问题是在 outputStream 和 inputStream 上都调用了委托(delegate)方法 Stream.Event.openCompleted,但是在 CFStreamCreatePairWithSocket 之后没有调用 Stream.Event.hasSpaceAvailable。
代码:-
if tls{
var readStream :Unmanaged<CFReadStream>?
var writeStream:Unmanaged<CFWriteStream>?
reset()
print("establish tls ")
tlsEnabled = true
let socketData = CFWriteStreamCopyProperty(self.outputStream as CFWriteStream,
CFStreamPropertyKey.socketNativeHandle) as! CFData
let native = CFSocketNativeHandle(CFDataGetBytePtr(socketData).pointee)
inputStream.close()
outputStream.close()
inputStream.remove(from: RunLoop.current, forMode: .defaultRunLoopMode)
outputStream.remove(from: RunLoop.current, forMode: .defaultRunLoopMode)
inputStream = nil
outputStream = nil
CFStreamCreatePairWithSocket(kCFAllocatorDefault,
native,
&readStream,
&writeStream)
inStream = readStream!.takeRetainedValue()
outStream = writeStream!.takeRetainedValue()
inStream.delegate = self
outStream.delegate = self
inStream.setProperty(kCFBooleanTrue, forKey: kCFStreamPropertyShouldCloseNativeSocket as Stream.PropertyKey)
outStream.setProperty(kCFBooleanTrue, forKey: kCFStreamPropertyShouldCloseNativeSocket as Stream.PropertyKey)
inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject,
forKey: Stream.PropertyKey.socketSecurityLevelKey)
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject,
forKey: Stream.PropertyKey.socketSecurityLevelKey)
let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false),
kCFStreamSSLPeerName: kCFNull]
inStream.setProperty(settings,
forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
outStream.setProperty(settings,
forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
inStream.schedule(in: RunLoop.current, forMode:.defaultRunLoopMode)
outStream.schedule(in:RunLoop.current, forMode:.defaultRunLoopMode)
inStream.open()
outStream.open()
最佳答案
问题似乎在于使用 CFSocket 创建套接字而不是直接创建 native 套接字句柄。
修改您的代码以直接使用 socket(_:_:_)
而不是使用 CFSocket 和 CFSocketNativeHandle 创建套接字会导致为我调用流委托(delegate)方法。
/**
Create sockaddr_in (IPV4) address for google.com
Note: If you need to resolve DNS for a hostname, use CFHost
*/
var remoteaddress = sockaddr_in()
inet_pton(PF_INET,
"207.47.131.217".cString(using: .utf8),
&sockaddress.sin_addr)
sockaddress.sin_port = UInt16(443).bigEndian
sockaddress.sin_family = sa_family_t(AF_INET)
// Create native socket handle, if sockhandle < 0, error occurred, (check errno)
let sockhandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
// if connectStatus < 0, error occurred (check errno)
let connectStatus = connect(sockhandle,
&remoteaddress,
socklen_t(MemoryLayout<sockaddr_in>.size))
var readStream :Unmanaged<CFReadStream>?
var writeStream:Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocket(kCFAllocatorDefault,
sockhandle,
&readStream, &writeStream)
关于sockets - 如何通过 CFSocketNativeHandle 使用 CFStreamCreatePairWithSocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40522837/