iOSによるソケット接続の確立

4942 ワード

rtmpプロトコルは、tcpベースのプロトコルであり、まずtcp接続を確立する必要がある.socketはtcpプロトコルのパッケージであるため、socketで接続を確立する.幸いなことに、アップルは私たちに簡単なインターフェースを提供してくれて、私たちが使いやすいです.コードは次のとおりです.
//.h  
 #import 

typedef NSStreamEvent SGStreamStatus;

@class SGStreamSession;
@protocol SGStreamSessionDelegate 

- (void)streamSession:(SGStreamSession *)session didChangeStatus:(SGStreamStatus)streamStatus;

@end

@interface SGStreamSession : NSObject

@property (nonatomic,assign,readonly) SGStreamStatus streamStatus;

@property (nonatomic,weak) id delegate;
//      
- (void)connectToServer:(NSString *)host port:(UInt32)port;
//    
- (void)disConnect;
//    
- (NSData *)readData;
//   
- (NSInteger)writeData:(NSData *)data;

@end

//.m  
 #import "SGStreamSession.h"
 #define SGLog NSLog

@interface SGStreamSession()
{
    NSInputStream  *_inputStream;
    NSOutputStream *_outputStream;
}
@end


@implementation SGStreamSession
- (instancetype)init{
    if (self = [super init]) {
        _streamStatus = NSStreamEventNone;
    }
    return self;
}
- (void)connectToServer:(NSString *)host port:(UInt32)port;{
    if (self.streamStatus > 0) {
        [self close];
    }
    
    //   ,    
    CFReadStreamRef  readStream;
    //   ,     
    CFWriteStreamRef writeStream;
    
   //rtmp       1935
    if (port <= 0) {
        port = 1935;
    }
    //    
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream);
    //  _bridge_transfer,         
    _inputStream           = (__bridge_transfer  NSInputStream  *)readStream;
    _outputStream          = (__bridge_transfer  NSOutputStream *)writeStream;

    _outputStream.delegate = self;
    _inputStream.delegate  = self;

    [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [_inputStream  scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    //         
    [_inputStream open];
    [_outputStream open];
}
#pragma mark -------delegate---------
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
    
    switch (eventCode) {
        case NSStreamEventNone: {
            return;//   return
        }
        case NSStreamEventOpenCompleted: {
            if (_inputStream == aStream ) {
                SGLog(@"    ");
                _streamStatus = NSStreamEventOpenCompleted;
            }
            break;
        }
        case NSStreamEventHasBytesAvailable: {
            SGLog(@"     ");
            _streamStatus |= NSStreamEventHasBytesAvailable;
            break;
        }
        case NSStreamEventHasSpaceAvailable: {
            SGLog(@"      ");
            _streamStatus |= NSStreamEventHasSpaceAvailable;
            break;
        }
        case NSStreamEventErrorOccurred: {
            SGLog(@"      ");
            _streamStatus = NSStreamEventErrorOccurred;
            break;
        }
        case NSStreamEventEndEncountered: {
            SGLog(@"    ");
            _streamStatus = NSStreamEventEndEncountered;
            break;
        }
    }
    
    if ([self.delegate respondsToSelector:@selector(streamSession:didChangeStatus:)]) {
        [self.delegate streamSession:self didChangeStatus:_streamStatus];
    }
}

- (void)disConnect{
    [self close];
}

- (void)close{
    
    [_inputStream  close];
    [_outputStream close];
    [_inputStream  removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    _streamStatus = NSStreamEventNone;
    _outputStream = nil;
    _inputStream  = nil;
    _inputStream.delegate = nil;
    _outputStream.delegate = nil;
}

- (void)dealloc{
    NSLog(@"%s",__func__);
    [self close];
}

- (NSData *)readData{
    
    uint8_t buff[4096];//    4K
    NSUInteger len = [_inputStream read:buff maxLength:sizeof(buff)];
    
   
    NSData *data = nil;
    
    if(len < sizeof(buff) && (_streamStatus & NSStreamEventHasBytesAvailable)){
        _streamStatus ^= NSStreamEventHasBytesAvailable;
        data = [NSData dataWithBytes:buff length:len];
    }
    
    return data;
}

- (NSInteger)writeData:(NSData *)data{
    if (data.length == 0) {
        return 0;
    }
    
    NSInteger ret = 0;
    if (_outputStream.hasSpaceAvailable) {
        ret = [_outputStream write:data.bytes maxLength:data.length];
    }
    
    if (ret > 0 && (_streamStatus & NSStreamEventHasSpaceAvailable)) {
        //     
        _streamStatus ^= NSStreamEventHasSpaceAvailable;
    }
    
    return ret;
}
@end



注釈はもう詳しく書いてある.ここで注意すると、中の状態処理が読めない場合は、葛藤しないでください|=と^=は=と考えることができます.深く理解したいなら、位列挙を見てもいいです.