iOS 建立socket連接

rtmp協(xié)議,是基于tcp的協(xié)議,首先我們需要建立起tcp連接.socket是對tcp協(xié)議的封裝,因此我們用socket來建立起連接.幸運(yùn)的是,蘋果給我們提供了簡單的接口,方便我們使用.
代碼如下:

//.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;
//連接到服務(wù)器
- (void)connectToServer:(NSString *)host port:(UInt32)port;
//斷開連接
- (void)disConnect;
//讀取數(shù)據(jù)
- (NSData *)readData;
//寫數(shù)據(jù)
- (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];
    }
    
    //輸入流,讀取數(shù)據(jù)
    CFReadStreamRef  readStream;
    //輸出流,負(fù)責(zé)寫數(shù)據(jù)
    CFWriteStreamRef writeStream;
    
   //rtmp協(xié)議默認(rèn)端口為1935
    if (port <= 0) {
        port = 1935;
    }
    //建立連接
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream);
    //注意_bridge_transfer,轉(zhuǎn)移內(nèi)存管理所有權(quán)
    _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(@"有字節(jié)可讀");
            _streamStatus |= NSStreamEventHasBytesAvailable;
            break;
        }
        case NSStreamEventHasSpaceAvailable: {
            SGLog(@"可以發(fā)送字節(jié)");
            _streamStatus |= NSStreamEventHasSpaceAvailable;
            break;
        }
        case NSStreamEventErrorOccurred: {
            SGLog(@"連接出現(xiàn)錯誤");
            _streamStatus = NSStreamEventErrorOccurred;
            break;
        }
        case NSStreamEventEndEncountered: {
            SGLog(@"連接結(jié)束");
            _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)) {
        //移除標(biāo)志位
        _streamStatus ^= NSStreamEventHasSpaceAvailable;
    }
    
    return ret;
}
@end


注釋已經(jīng)寫得很詳細(xì)了.這里提醒一下,里面的狀態(tài)處理如果看不懂,不要糾結(jié),|= 和 ^= 可以認(rèn)為是 = .如果想深入了解,可以看看位枚舉.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、網(wǎng)絡(luò)各個協(xié)議:TCP/IP、SOCKET、HTTP等 網(wǎng)絡(luò)七層由下往上分別為物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層...
    杯水救車薪閱讀 2,367評論 0 17
  • 1.項(xiàng)目經(jīng)驗(yàn) 2.基礎(chǔ)問題 3.指南認(rèn)識 4.解決思路 ios開發(fā)三大塊: 1.Oc基礎(chǔ) 2.CocoaTouch...
    扶光啟玄閱讀 5,208評論 0 13
  • 第一部分、概念的理解1、什么是Socket?Socket又稱之為“套接字”,是系統(tǒng)提供的用于網(wǎng)絡(luò)通信的方法。它的實(shí)...
    Hevin_Chen閱讀 2,633評論 0 5
  • 1.1 TCP/IP協(xié)議組 TCP/IP協(xié)議(傳輸控制協(xié)議)由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成 IP層負(fù)責(zé)...
    F麥子閱讀 2,925評論 0 25
  • 我個人的讀書歷史:我讀了大概幾百本書,雖然不算很多,但也勉強(qiáng)可以指導(dǎo)入門級的了,使他們少走些彎路,我的第...
    張潔小確幸閱讀 493評論 2 3

友情鏈接更多精彩內(nèi)容