保持一个套接字连接活着的iOS(Keeping a socket connection alive

2019-06-26 03:31发布

我用Objective-C下面的代码,一个套接字写入数据。 该服务器运行在Ubuntu之上的node.js:

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分钟左右?)之后。 我怎样才能继续保持该连接活着吗? 我知道有一个脱节,因为同样的事情发生,如果我连接到终端下的服务器,我必须保持该连接活着。 我想同样的事情在我的代码发生。 谢谢你的帮助!

Answer 1:

最简单的答案是尝试使用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包到您的协议,并定期发送ping包,所以你可以检测断开的连接。



Answer 2:

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

socket.setKeepAlive(true, 2000);

而在这样的节点保持每个插座打开。 默认是假的,所以这就是为什么它被超时。 我希望这是对别人有用。 感谢您为您的答复,我想保持心跳(保持活动)也是一个不错的想法,但这种做法本地节点照顾它。



Answer 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));
    }

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



Answer 4:

你需要定期发送一些垃圾上的连接。 试试这个:

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);
}

注意:更换`“保持连接!” 不管你想为您的协议。 唯一的要求是,所述远端(套接字服务器)忽略该消息。



文章来源: Keeping a socket connection alive in iOS