sockets - 如何通过 CFSocketNativeHandle 使用 CFStreamCreatePairWithSocket

标签 sockets ssl xmpp swift3

我正在尝试为 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/

相关文章:

客户端使用C使用TCP套接字将数据发送到端口

python-2.7 - SSL证书下载

ssl - 谷歌云数据融合如何接受自签名证书

android - 如何为 facebook 创建 XMPP 聊天客户端?

android - 如何使用 Smack 了解 XMPP openfire 中的键入状态

c - 套接字编程-简单的客户端/服务器

c# - 如何在 C# 中为大型 HTTP 请求设置 HttpWebRequest.Timeout

amazon-web-services - 主域上的 EV SSL 和子域上的 Wildcard SSL

xmpp - XMPP 服务器可以存储离线消息多长时间

sockets - 如何在 Telnet 中创建 HTTP 请求