iOS -- 原生NSStream实现socket

Posted ⬆️小马哥⬆️

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS -- 原生NSStream实现socket相关的知识,希望对你有一定的参考价值。

- (void)startSocket:(NSString *)address andPort:(int)port
{
    CFReadStreamRef readRef;
    CFWriteStreamRef writeRef;
    
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)address, port, &readRef, &writeRef);
    
    _inputStream = (__bridge NSInputStream *)readRef;
    _outputStream = (__bridge NSOutputStream *)writeRef;
    
    // 设置流属性
    [_inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];
    [_outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];
    
    // 设置代理
    _inputStream.delegate = self;
    _outputStream.delegate = self;
    
    // 放到runloop中
    [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    [_inputStream open];
    [_outputStream open];
}

// 断开 scoket 连接
- (void)closeSocket {
    if(_inputStream){
        _inputStream.delegate = nil;
        [_inputStream close];
        [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        _inputStream = nil;
    }
    if(_outputStream){
        _outputStream.delegate = nil;
        [_outputStream close];
        [_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        _outputStream = nil;
        [SVProgressHUD showSuccessWithStatus:@"断开连接成功"];
    }
    // 通知给界面
    [[NSNotificationCenter defaultCenter] postNotificationName:@"closeSocket" object:nil userInfo:nil];
}

// 代理的回调是在主线程
#pragma mark - <NSStreamDelegate>代理方法
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode) {
        case NSStreamEventNone:
            break;
        case NSStreamEventOpenCompleted:
            [SVProgressHUD showSuccessWithStatus:@"连接成功"];
            NSLog(@"成功建立连接, 形成输入输出管道");
            break;
        case NSStreamEventHasBytesAvailable:
            NSLog(@"有数据可读");
        {
            uint8_t buf[3072];
            NSInteger len = 0;
            NSInputStream *inputStream = (NSInputStream *)aStream;
            len = [inputStream read:buf maxLength:3072];
            
            if (len) {
                _tempString = [NSMutableString string];
                // 将16进制字符拼接起来
                for (int i = 0; i < len; i++) {
                    NSMutableString *str = [NSMutableString stringWithFormat:@"%x", buf[i]];
                    if (str.length < 2) {
                        [str insertString:@"0" atIndex:0];
                    }
                    [_tempString appendString:str];
                }
                // 进行分包丶 粘包处理, 同时进行KVO监听可用的包
                
                    [_stick_Subcontract_Package HandleResultOnReceiveData:_tempString];
               
            }
            break;
        }
        case NSStreamEventHasSpaceAvailable:
            NSLog(@"可以发送数据");
            break;
        case NSStreamEventErrorOccurred:
            NSLog(@"有错误发生, 连接失败");
            [SVProgressHUD showErrorWithStatus:@"连接错误"];
        {
            [aStream close];
            break;
        }
        case NSStreamEventEndEncountered:
            [SVProgressHUD showErrorWithStatus:@"正常断开连接"];
            NSLog(@"正常断开连接");
            
        {
            [aStream close];
            [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            aStream = nil;
            break;
        }
            
        default:
            break;
    }
}

有个问题, 就是这个没有实现异步接受消息.所以最好用asynSocket

以上是关于iOS -- 原生NSStream实现socket的主要内容,如果未能解决你的问题,请参考以下文章

[深入浅出Cocoa]iOS网络编程之NSStream

NSStream 和 Sockets,未调用 NSStreamDelegate 方法

NSStream实现发送和接受数据

iOS网络底层实现

iOS网络底层实现

原生 nodejs 结合 Socket.io 实现服务器和 客户端的相互通信