iOS 建立socket连接

作者: youngyunxing | 来源:发表于2016-08-02 00:25 被阅读379次

    rtmp协议,是基于tcp的协议,首先我们需要建立起tcp连接.socket是对tcp协议的封装,因此我们用socket来建立起连接.幸运的是,苹果给我们提供了简单的接口,方便我们使用.
    代码如下:

    //.h文件
     #import <Foundation/Foundation.h>
    
    typedef NSStreamEvent SGStreamStatus;
    
    @class SGStreamSession;
    @protocol SGStreamSessionDelegate <NSObject>
    
    - (void)streamSession:(SGStreamSession *)session didChangeStatus:(SGStreamStatus)streamStatus;
    
    @end
    
    @interface SGStreamSession : NSObject
    
    @property (nonatomic,assign,readonly) SGStreamStatus streamStatus;
    
    @property (nonatomic,weak) id<SGStreamSessionDelegate> 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()<NSStreamDelegate>
    {
        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
    
    
    

    注释已经写得很详细了.这里提醒一下,里面的状态处理如果看不懂,不要纠结,|= 和 ^= 可以认为是 = .如果想深入了解,可以看看位枚举.

    相关文章

      网友评论

        本文标题:iOS 建立socket连接

        本文链接:https://www.haomeiwen.com/subject/iarfsttx.html