2012-07-08 43 views
11

我有以Objective-C编写的将数据写入套接字的代码。服务器在Ubuntu上运行node.js:在iOS中保持套接字连接有效

NSString *url = @"anIPAddress";   
CFReadStreamRef readStream; 
CFWriteStreamRef writeStream;    
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)url, 9000, &readStream, &writeStream); 
self.inputStream = (NSInputStream *)readStream;    
self.outputStream = (NSOutputStream *)writeStream; 
[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]; 

我可以连接到服务器并发送信息。不过,我注意到几分钟后连接超时(我想5分钟左右?)。我怎样才能保持这种联系?我知道有一个断开连接,因为如果我连接到终端下的服务器,同样的事情发生,我必须保持连接活着。我想象我的代码中正在发生同样的事情。谢谢你的帮助!

+0

对于有效的Objective-C代码,请参考[下面的答案](http://stackoverflow.com/a/25725181)... – Despotovic 2016-02-03 23:08:15

回答

3

我发现如何做到这一点。由于服务器正在运行的node.js,我用

socket.setKeepAlive(true, 2000); 

并以这种方式保持节点的每个插座打开。默认值是false,所以这就是它超时的原因。我希望这对其他人有用。感谢您的回复,我认为保持心跳(保持活跃状态​​)也是一个好主意,但是通过这个本地方法节点来处理它。

+0

您开始使用ios流,现在您正在工作克与套接字对象?你在这里用什么样的api? – 2012-12-26 16:23:01

+1

@ItayLevin他向你展示了他是如何在服务器上完成它的 - 请参阅下面的答案以了解如何在iOS上执行此操作。 – 2013-02-10 23:25:43

6

最简单的答案是尝试使用SO_KEEPALIVE套接字选项。

如果没有数据在端点之间流动,断开的连接可能很难检测到,这使得此选项在某些方面无用,因为它不使用数据来检测断开的连接。但是,添加到您的代码很容易看到。添加它,看看它是否有助于...

这是它是如何用C实现或C++

int opt = 1; 
// Get the native socket handle from your socket class here... 
int socket_handle = getNativeSocketHandle(self.outputStream); 

/*Enabling keep alive*/ 
if(setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)) < 0) 
{ 
    // failed setting socket option 
} 

的不那么简单的答案是一个ping包添加到您的协议和发送平定期打包,以便您可以检测到连接断开。

+0

嗯。有没有一种方法可以在Objective-C中使用上面的API来做到这一点? – Hahnemann 2012-07-09 01:26:35

+0

@Hahnemann:我不太了解Objective-C,所以我不知道。然而,我敢打赌,有一个逃生舱来打电话给C库。 – JimR 2012-07-09 02:57:36

+0

@Hahnemann:看看这里:http://developer.apple.com/library/ios/DOCUMENTATION/CoreFoundation/Reference/CFStreamConstants/Reference/reference.html#//apple_ref/doc/c_ref/kCFStreamPropertySocketNativeHandle,看看它是否帮助。 – JimR 2012-07-09 03:03:12

3

您需要定期通过连接发送一些垃圾。试试这个:

NSTimer* t = [NSTimer scheduledTimerWithTimeInterval:240 target:self selector:@selector(timerMethod:) userInfo:[NSNumber numberWithInt:sockfd] repeats:YES]; 

然后在self声明如下:

-(void)timerMethod:(NSTimer*)t 
{ 
    send([[t userInfo] intValue], "Keepalive!", 11, 0); 
} 

注:更换` “保持连接!”与任何你想要的协议。唯一的要求是远程端(套接字服务器)忽略消息。

+0

是否有设置超时限制?我想知道在什么频率我应该发送垃圾数​​据 – 2012-07-09 00:14:43

+0

@用户:连接需要多长时间才能死亡?在此之前安排一下。 – Linuxios 2012-07-09 00:20:12

+1

在某些情况下,您可能想将其视为套接字服务器上的“心跳数据”,而不是“垃圾”。 ) – 2013-05-17 17:11:48

3

假设一个NSOutputStream * oStream;

在iOS这样来做:

#if 1 // Using CF 
CFDataRef data = (CFDataRef)CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)oStream, kCFStreamPropertySocketNativeHandle); 
if(data) { 
    CFSocketNativeHandle socket_handle = *(CFSocketNativeHandle *)CFDataGetBytePtr(data); 
    CFRelease(data); 
#else // Using Foundation 
NSData *data = (NSData *)[oStream propertyForKey:(__bridge NSString *)kCFStreamPropertySocketNativeHandle]; 
if(data) { 
    CFSocketNativeHandle socket_handle = *(CFSocketNativeHandle *)[data bytes]; 
#endif 
    NSLog(@"SOCK HANDLE: %x", socket_handle); 

    /*Enabling keep alive*/ 
    if(setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)) < 0) 
    { 
     NSLog(@"Yikes 2: failed to set keepalive! ERRNO: %s", strerror(errno)); 
    } 

我张贴这一点,因为我只花了几个小时了这一切,要保存别人的努力。

+0

socket_handle,SOL_SOCKET,SO_KEEPALIVE的值是什么? – Rohan 2013-05-13 11:12:25

+0

man 2 setsockopt或在Xcode文档视图中搜索setsockopt。 – 2013-05-13 15:13:14

+2

只有苹果能够做出如此简单,如此复杂的事情。我使用Berkley Sockets编写了网络应用程序,并且它比这更简单。 – deusprogrammer 2015-01-13 18:11:42