NSStream TCP保持活动的iOS(NSStream TCP Keep-alive iOS)

2019-08-19 05:41发布

我写了这个代码设置与服务器流:

-(void)streamOpenWithIp:(NSString *)ip withPortNumber:(int)portNumber;
{
       CFReadStreamRef readStream;
       CFWriteStreamRef writeStream;
       CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)ip, portNumber, &readStream, &writeStream);

       if(readStream && writeStream)
       {
            CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
            CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);

            //Setup inpustream
            inputStream = (__bridge NSInputStream *)readStream;
            [inputStream setDelegate:self];
            [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [inputStream open];

            //Setup outputstream
            outputStream = (__bridge NSOutputStream *)writeStream;
            [outputStream setDelegate:self];
            [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream open];
       }
}

我能够连接到服务器并发送和接收数据。 但我想,以检查是否关联仍然存在。 如果我断开WiFi路由器的电缆,我仍然可以在流中发送数据并没有出错。

您可以通过使用定时器来发送一些信息,并查看是否收到了东西回来在应用层上解决这个问题。 但是你可以用在一个较低的水平TCP保活技术还解决这个问题。

我怎样NSStream实现这个? 如何设置检查的间隔?

我假设你得到一个NSStreamEventErrorOcurred时,流下来通过TCP保持活动的检查呢?

我已经检查了这个职位,但我无法弄清楚: 保持一个套接字连接活着的iOS

谢谢你的帮助!

Answer 1:

你可以得到与本地套接字句柄

CFDataRef socketData = CFReadStreamCopyProperty((__bridge CFReadStreamRef)(inputStream), kCFStreamPropertySocketNativeHandle);
CFSocketNativeHandle socket;
CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket);
CFRelease(socketData);

然后设置套接字选项(你需要#include <sys/socket.h>此):

int on = 1;
if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1) {
   NSLog(@"setsockopt failed: %s", strerror(errno));
}

你可以把这个代码的事件处理函数kCFStreamEventOpenCompleted事件:

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {
    switch (event) {
        case kCFStreamEventOpenCompleted:
            if (stream == self.inputStream) {
                CFDataRef socketData = CFReadStreamCopyProperty((__bridge CFReadStreamRef)(stream), kCFStreamPropertySocketNativeHandle);
                CFSocketNativeHandle socket;
                CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket);
                CFRelease(socketData);

                int on = 1;
                if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1) {
                    NSLog(@"setsockopt failed: %s", strerror(errno));
                }
            }
            break;

        /* ... other cases ... */;
    }
}


Answer 2:

此委托方法使连接的流状态。 你可以在这里检查您的连接状态

 -(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {
    NSLog(@"Stream triggered.");
    switch(event) {
            case (NSStreamStatus)NSStreamEventErrorOccurred:
        {

            NSLog(@"%@",[stream streamError].localizedDescription);

        }
            break;
        case NSStreamEventHasSpaceAvailable: {
            if(stream == outputStream) {
                NSLog(@"outputStream is ready.");
            }
            break;
        }
        case NSStreamEventHasBytesAvailable: {
            if(stream == inputStream) {

                   NSLog(@"data can be read here!");

                }
            }
            break;
        }
        default: {


            NSLog(@"Stream is sending an Event: %i", event);
            break;
        }
    }
}


Answer 3:

还有一个更完整的答案类似的问题。

对于开始10秒后发送激活该应用程序的例子,发送keppalive每2秒和关闭后4保持连接,没有答复流,看看这篇文章: 是否有可能激活Apple iOS设备TCP存活

这也显示了如何设置重传超时后连接被关闭。



文章来源: NSStream TCP Keep-alive iOS