Apple TLS与Objective-C和Swift的区别
问题描述:
我正在使用Apple的CFNetworking获取TLS流。我在将Objective-C代码移植到Swift时遇到了一些麻烦。Apple TLS与Objective-C和Swift的区别
使用完全相同的步骤,它在使用Objective-C时起作用,但在尝试使用Swift时握手始终失败。
工作对象 -
- (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];
}
非工作斯威夫特
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的屏幕抓取:
工作对象 -
非工作斯威夫特
我为正在发生的事情是很笨。我不知道为什么Obj-C版本使用TLS v1.2启动Client Hello,但Swift尝试使用TLS v1.0,然后放弃。不知道为什么Swift版本需要这么长时间才能发送客户端Hello,Keepalive数据包是先发送的?任何帮助将不胜感激。
答
原来没有什么区别,我只是一个白痴。一旦NSStreamEvent.OpenCompleted
事件被输入输出流调用,我立即调用outputStream.write()
。这是写入SSL握手的缓冲区,并搞砸了。
直到我为Obj-c和Swift创建了一个MVP,它才表明如果你花时间创建一个有效的MVP,那么在编写它时可能会弄清楚它。现在,如果我只能在握手完成后找到通知的方式,则始终可以避免此问题。
这可能不会改变任何内容,但是您设置NSStreamSocketSecurityLevelNegotiatedSSL和委托的顺序在您的ObjC和Swift版本之间交换。 – zneak
这并不重要。握手直到在流的任一端上进行第一次读取或写入调用才开始。 – nathansizemore
这个'connect()'方法被调用的上下文怎么样?它在主线程上吗? –