ios - NSStream TCP 保活 iOS

标签 ios objective-c tcp keep-alive nsstream

我编写了这段代码来设置服务器流:

-(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 Keep-Alive 技术来解决这个问题。

如何使用 NSStream 实现它?如何设置检查间隔?

我假设您通过使用 TCP Keep-Alive 检查流中断时收到 NSStreamEventErrorOcurred?

我已经检查了这篇文章,但我无法弄明白: Keeping a socket connection alive in iOS

感谢您的帮助!

最佳答案

您可以通过以下方式获取 native 套接字句柄

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 ... */;
    }
}

关于ios - NSStream TCP 保活 iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15785917/

相关文章:

c++ - C++ 中的 TCP/IP 服务器不等待客户端

c - 确定客户端绑定(bind)到的 TCP 端口号

iphone - 如何在其中键入时调整 UITextView 的大小?

ios - 根据用户位置动态绘制RMShape

mysql - panic : dial tcp 127. 0.0.1:3306: 连接: 连接被拒绝

objective-c - 显示背景图像、图像和标题的 UIButton

ios - 核心数据 - 如何初始化与 CSV 文件中的另一个实体有关系的实体?

ios - 快速将公历日期选择器转换为波斯日期选择器?

ios - Swift Dictionary 为同一个键返回不同的对象

objective-c - 使用 NSFetchedResultsController 删除部分中的最后一行 -> 崩溃