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连接

    rtmp协议,是基于tcp的协议,首先我们需要建立起tcp连接.socket是对tcp协议的封装,因此我们用soc...

  • 2018-03-12

    ios开发Socket简单使用 建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(AP...

  • socket

    Socket连接与HTTP连接的不同 通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信...

  • TCP HTTP Soket

    1、TCP连接 2、HTTP连接 3、SOCKET原理 3.1套接字(socket)概念 3.2 建立socket...

  • 第二篇:socket编程

    目录一、socket是什么?二、socket连接与HTTP连接的区别三、如何建立一个socket连接?四、使用OC...

  • 接口测试基础

    一、HTTP请求过程: 1、 连接:建立一个socket连接,因为socket是通过IP+端口建立的,在这之前会进...

  • 网络通信-----Socket

    Socket:又称套接字,底层要建立连接通道,通过套接字建立连接,向网络发出应答或请求 套接字(socket)是通...

  • (二)即时通讯系列之TCP Socket

    即时通讯系列之Socket简介 一、Socket连接 1.连接过程 建立Socket连接至少需要一对套接字,其中一...

  • 长连接和心跳

    长连接实现的几种方式 socket建立长连接并发送心跳

  • 网络连接与传输建立过程

    网络连接与传输建立过程 Socket连接 Socket 以服务器 ip 和端口号创建一个 Socket 套接子,对...

网友评论

    本文标题:iOS 建立socket连接

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