运维开发网

NSStream TCP Keep-alive iOS

运维开发网 https://www.qedev.com 2020-05-29 10:29 出处:网络 作者:运维开发网整理
我已编写此代码来设置服务器的流: -(void)streamOpenWithIp:(NSString *)ip withPortNumber:(int)portNumber; { CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToH
我已编写此代码来设置服务器的流:

-(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

谢谢你的帮助!

您可以使用本机套接字句柄

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

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号