Objective-C 和 Swift 的 Apple TLS 之间的区别
Difference between Apple TLS with Objective-C and Swift
我正在使用 Apple 的 CFNetworking 获取 TLS 流。我在将 Objective-C 代码移植到 Swift 时遇到了一些麻烦。
使用完全相同的步骤,它在使用 Objective-C 时有效,但在尝试使用 Swift 时握手始终失败。
工作目标-c
- (void)connect()
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(__bridge CFStringRef)hostAddress,
port,
&readStream,
&writeStream);
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[self.inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
[self.outputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
}
不工作Swift
func connect() {
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
let host = "some_host"
let hostAsCFString = host as NSString
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
hostAsCFString,
1337,
&readStream,
&writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
inputStream!.delegate = self
outputStream!.delegate = self
inputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL,
forKey: NSStreamSocketSecurityLevelKey)
outputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL,
forKey: NSStreamSocketSecurityLevelKey)
inputStream!.scheduleInRunLoop(.currentRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(.currentRunLoop(), forMode: NSDefaultRunLoopMode)
inputStream!.open()
outputStream!.open()
}
两者都试图连接到相同的服务器和相同的端口。
wireshark 的屏幕截图:
工作对象 C
不工作 Swift
我对发生的事情一无所知。我不知道为什么 Obj-C 版本使用 TLS v1.2 启动 Client Hello,但是 Swift 尝试使用 TLS v1.0,然后就放弃了。不知道为什么 Swift 版本需要这么长时间才能发送 Client Hello,之前会发送 Keepalive 数据包?任何帮助将不胜感激。
原来没有什么区别,我就是个白痴。一旦为输入和输出流调用了 NSStreamEvent.OpenCompleted
事件,我立即调用 outputStream.write()
。它正在写入 SSL 握手的缓冲区,并把它搞得一团糟。
在我为 Obj-c 和 Swift 创建一个 MVP 之前找不到,这只是表明如果你花时间创建一个有效的 MVP,你可能会在编写时弄清楚它。现在,如果我能想办法在握手完成后得到通知,这个问题就永远可以避免了。
我正在使用 Apple 的 CFNetworking 获取 TLS 流。我在将 Objective-C 代码移植到 Swift 时遇到了一些麻烦。
使用完全相同的步骤,它在使用 Objective-C 时有效,但在尝试使用 Swift 时握手始终失败。
工作目标-c
- (void)connect()
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(__bridge CFStringRef)hostAddress,
port,
&readStream,
&writeStream);
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[self.inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
[self.outputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
}
不工作Swift
func connect() {
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
let host = "some_host"
let hostAsCFString = host as NSString
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
hostAsCFString,
1337,
&readStream,
&writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
inputStream!.delegate = self
outputStream!.delegate = self
inputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL,
forKey: NSStreamSocketSecurityLevelKey)
outputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL,
forKey: NSStreamSocketSecurityLevelKey)
inputStream!.scheduleInRunLoop(.currentRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(.currentRunLoop(), forMode: NSDefaultRunLoopMode)
inputStream!.open()
outputStream!.open()
}
两者都试图连接到相同的服务器和相同的端口。
wireshark 的屏幕截图:
工作对象 C
不工作 Swift
我对发生的事情一无所知。我不知道为什么 Obj-C 版本使用 TLS v1.2 启动 Client Hello,但是 Swift 尝试使用 TLS v1.0,然后就放弃了。不知道为什么 Swift 版本需要这么长时间才能发送 Client Hello,之前会发送 Keepalive 数据包?任何帮助将不胜感激。
原来没有什么区别,我就是个白痴。一旦为输入和输出流调用了 NSStreamEvent.OpenCompleted
事件,我立即调用 outputStream.write()
。它正在写入 SSL 握手的缓冲区,并把它搞得一团糟。
在我为 Obj-c 和 Swift 创建一个 MVP 之前找不到,这只是表明如果你花时间创建一个有效的 MVP,你可能会在编写时弄清楚它。现在,如果我能想办法在握手完成后得到通知,这个问题就永远可以避免了。