【发布时间】:2014-10-29 05:22:57
【问题描述】:
Apple 设备 === 路由器 === WiFi 模块
Apple 设备 (iPhone) 正在通过 TCP 连接连接到 WiFi 模块端口 2000。我想在 Apple 设备上激活 TCP keepalive 数据包发送,以了解与 WiFi 模块的 TCP 连接何时丢失(模块已关闭)。
我的直播设置
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)CFBridgingRetain(moduleIPaddress), port2000, &readStream, &writeStream);
outputStream = (NSOutputStream *)CFBridgingRelease(writeStream);
inputStream = (NSInputStream *)CFBridgingRelease(readStream);
[outputStream setDelegate:(id)self];
[inputStream setDelegate:(id)self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];
[inputStream open];
根据David H post Keeping socket connection alive in iOS,我尝试激活keepalive
- (void) stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
if (theStream == outputStream) {
/*
CFDataRef data = (CFDataRef)CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)theStream, kCFStreamPropertySocketNativeHandle);
if(data) {
CFSocketNativeHandle socket_handle = *(CFSocketNativeHandle *)CFDataGetBytePtr(data);
CFRelease(data);
NSLog(@"SOCK HANDLE: %x", socket_handle);
//Enabling keep alive
int opt = 1;
if( setsockopt( socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof( opt ) ) < 0 )
{
NSLog(@"Yikes 2: failed to set keepalive! ERRNO: %s", strerror(errno));
}
}
*/
NSData *data = (NSData *)[theStream propertyForKey:(__bridge NSString *)kCFStreamPropertySocketNativeHandle];
if(data) {
CFSocketNativeHandle socket_handle = *(CFSocketNativeHandle *)[data bytes];
NSLog(@"SOCK HANDLE: %x", socket_handle);
//Enabling keep alive
int opt = 1;
if( setsockopt( socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof( opt ) ) < 0 )
{
NSLog(@"Yikes 2: failed to set keepalive! ERRNO: %s", strerror(errno));
}
}
}
两个选项都打印出 SOCK HANDLE: 9 ,没有错误消息。当 WiFi 模块关闭时,连接仍然保持打开状态 30 分钟或更长时间,而我没有将数据发送到输出流。如果我将数据发送到输出流,我会在大约 60 秒后得到 NSStreamEventErrorOccurred - Error Domain=NSPOSIXErrorDomain Code=60 "The operation could not be completed. Operation timed out"。我用苹果设备试过这个。当我尝试使用 iOS 模拟器时,我没有看到使用 Wireshark 的 keepalive 数据包。
NSStream tcp keepalive in iOS 还描述了保活设置。 Martin R 示例代码为似乎错误的输入流激活了 keepalive。
是否可以在 iPhone 等 Apple iOS 设备上激活 TCP keepalive(应该按照 David H 的说法)?如果可能的话应该怎么做(我的代码中缺少什么)?
【问题讨论】: