美文网首页socketIOS
SocketRocket - facebook

SocketRocket - facebook

作者: 桃逸 | 来源:发表于2017-03-17 19:38 被阅读537次

    socketRocket

    WebSocket 协议

    百度百科
    http://www.tuicool.com/articles/7zyMvy6

    HTML5一种新的协议,实现了浏览器与服务器全双工通信,一开始的握手需要借助HTTP请求完成;
    传统的HTTP请求采用轮询,而HTTP的header是非常长的,这样会占用很多带宽;
    WebSocket API中,浏览器只需要做一个握手的动作,然后,浏览器和服务器之间形成了一条快速通道,两者之间就直接可以数据互相传送;
    HTTP的keep-alive是把多个http请求合并为一个,而Websocket是一个新协议;


    Paste_Image.png

    多出的 Upgrade,Connection字段表明是websocket请求;

    • 数据帧格式
      基本的数据帧为一个opcode、一个payload长度和发送的应用数据
      Paste_Image.png

    1. 测试用例

    2. 技术点

    NSOperation

    NSOperation 方法说明
    (void)start; 启动 operation
    isFinished, isExecuting 状态标识
    在start函数里处理设计要执行的功能

    • 设计 operation
      设计一个基础的SRTWebSocketOperation<SRWebSocketDelegate>, 并代理处理SR webSocket的close及fail事件;
      SRAutobahnOperation : SRTWebSocketOperation 实际设计执行的子operation, 并处理delegate中消息接收的事件;
      设计了三个测试接口:
      SRAutobahnTestResultOperation 结果
      SRAutobahnTestCaseInfoOperation 信息
      SRAutobahnTestCaseCountOperation 数目
      SRAutobahnTestUpdateReportsOperation 更新
      每个接口创建对应的url测试

    • operation queue
      NSOperationQueue
      addDependency //依赖任务完成偶才开始执行其他任务
      addOperation

    • __bridge
      __bridge 关键字来实现id类型与void*类型的相互转换;
      __bridge_retained 是编译器替我们做了retain工作;
      __bridge_transfer 是编译器替我们做了release工作;

    NSURL 使用

    NSURLComponents
    NSURLQueryItem

    BLOCK

    block copy ??? 使用copy有什么用途??//[textMessageHandler copy]
    __block 定义变量,让block内部可改变

    手动KVO

    willChangeValueForKey / didChangeValueForKey 即时状态不变化也能触动observation?

    DSP

    DSP中的block使用self不会引起循环引用,使用weakSelf的是为了减少self的生命周期;因为block肯定会执行;

    • 使用 dispatch_group_t 同步
      diapatch_group_create / dispacth_group_enter / dispatch_group_wait / dispatch_group_leave
    • 使用 dispatch_semaphore_t 进行同步
    • dispatch_data_t
      某种程度上跟NSData类型相似;
      它的独特属性是它可以基于零碎的内存区域,对组合内存进行连接管理;
      dispatch_data_t c = dispatch_data_create_concat(a, b);
      它并不把数据copy到一个单独的更大的内存区域,相反的只是简单简单持有a和b对象;
      类似的,你可以使用dispatch_data_create_subrange来创建一个不做任何拷贝操作的子区域;
    • dispatch_benchmark
      测试代码执行的平均纳秒数,只在调试和性能分析上起作用;
    编译相关

    attribute ((vector_size (32))); 占32字节
    _Alignof(type-name) 某类型的对齐要求

    3. 结构设计

    Paste_Image.png

    4. 模块

    Internal 模块

    SRPinningSecurityPolicy : SRSecurityPolicy

    使用 Security 框架

    • evaluateServerTrust
      遍历serverTrust对象,检查是否与pinnedCertificates中的某个证书一致,当验证所有pinned证书都正确时,返回YES,否则NO;
    • updateSecurityOptionsInStream
      设置NSStream对象的安全属性策略,支持TLS,是否支持证书链;
    SRProxyConnect :NSObject

    使用 NSStreamDelegate 代理,使用 CFNetwork 框架;
    处理url的代理设置,有代理连接代理,无代理直接访问host;
    属性:http与socket代理,SSL支持,输入数据数组

    • initWithURL:(NSURL *)url
      初始化工作,检查url是否需要SSL;
      创建写数据的 dispatch_queue,初始化输入数据数组
    • _configureProxy 取得系统代理并设置代理
      _fetchPAC 根据url自动发现代理,再调用_runPACScript取得代理设置
      _runPACScript 运行PAC的JS脚本取得代理设置
      _readProxySettingWithType 读取http或socket代理设置保存
    • _openConnection
      NSStream Foundation架构中定义
      _initializeStreams 根据url跟代理配置连接参数,调用CFStreamCreatePairWithSocketToHost 创建socket的read和write stream;
      NSInputStream / NSOutputStream open 打开stream;
    • (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode;
      处理socket的read/write stream的代理事件,包括连接、错误、数据事件的处理;
      如果stream打开成功,检查是否有http代理,如果有发送http代理连接请求;
    • _didConnect
      表示根据代理设置已连接成功的处理,返回;
      设置input/outputStream为nil,取消代理,回调_completion;
    • _writeData
      这个数据只会是代理连接的请求数据;
      将数据写入到outStream中,并做错误与超时处理;
    • _processInputStream
      读取inputStream的数据放入到input队列中;
      CFHTTPMessageAppendBytes 将数据放入到代理头中,
      调用_proxyProcessHTTPResponseWithData检查代理是否连上了;
    SRDelegateController :NSObject

    设置DSP或者Operation来处理delegate的block;

    IOConsumerPool :NSObject

    存储管理poolSize个SRIOConsumer;

    • consumerWithScanner
      从pool中取出一个SRIOConsumer或者创建一个,并设置参数返回consumer;
    • returnConsumer
      向pool中添加一个consumer;
    IOConsumer

    管理io接口属性

    • resetWithScanner
      根据传入参数设置stream_scanner / data_callback函数指针,设置_bytesNeeded/_readToCurrentFrame/_unmaskBytes
    SRRunLoopThread :NSThread 自定义线程类

    通过自定义main 中 runloop来控制循环不退出,同时记录线程的 runloop

    • main 函数:添加一个空的 runloop source,并加入到 current runloop中,保持线程一直阻塞等待事件触发?

    Utilities 模块

    提供各种C接口工具函数

    SRHash

    对数据进行sha1或者base64编码
    SHA1: Secure Hash Algorithm 安全哈希算法
    Base64:网络上最常见的用于传输8Bit字节代码的编码方式之一,返回一个字符串;

    SRHTTPConnectMessage

    根据request,secureKey,协议版本,cookie及协议,来生成一个CFHTTPMessageRef的Http消息头;
    CFHTTPMessageSetHeaderFieldValue:设置http消息头的字段,包括GET/Host/Cookie/Authorization/Connection/Sec-WebSocket-Key/Sec-WebSocket-Version/Sec-WebSocket-Protocol以及request中的key字段;

    SRURLUtilities
    • SRURLRequiresSSL
      取得NSURL中的host,port,schema组织成一个 https://127.0.0.1:90像是的字符串;
    • SRURLRequiresSSL
      检查NSURL的schema中是否为wss还是https(表示SSL协议);
    • SRStreamNetworkServiceTypeFromURLRequest
      把NSURLRequest中的networkServiceType转换为NSStream类型的字符串;
      服务类型包括:默认正常、VoIP、Video、Background、Voice及Call Signaling;
    SRSIMDHelpers

    对数据进行SIMD的处理,使用多数据流能够加快数据处理

    • SIMD
      SIMD:Single Instruction Multiple Data 单指令多数据流,能够复制多个操作数,并把它们打包在大型寄存器的一组指令集;
      以加法指令为例,单指令单数据(SISD)的CPU对加法指令译码后,执行部件先访问内存,取得第一个操作数;之后再一次访问内存,取得第二个操作数;随后才能进行求和运算。而在SIMD型的CPU中,指令译码后几个执行部件同时访问内存,一次性获得所有操作数进行运算。这个特点使SIMD特别适合于多媒体应用等数据密集型运算;

    Socket Rocket 模块

    Paste_Image.png
    SRWebSocket

    主要连接接口及数据处理在这里面
    SRWebSocketDelegate : handle status and message events
    Constructor / open
    属性:涉及NSURLRequest、SRSecurityPolicy、SRDelegateController、SRIOConsumer等对象;

    • (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates
      根据请求URL,协议,是否接受不信任的SSL证书,来创建请求;
      SRSecurityPolicy用来处理设置stream的安全策略;
      这个函数用于处初始化各个参数;
    • open
      超时处理、SRProxyConnect进行连接;
      在block中取得连接的 input/outputStream
      如果需要验证SSL,在接收到stream数据后对证书进行验证;
    • didConnect
      生成随机key,生成并发送webSocket的http连接请求消息;
      _pumpWriting 将数据写入到 _outputStream 发送出去;
    • sendString
      对数据进行frame组织并发送给webSocket服务端;参考webSocket协议;
      sendString --> _sendFrameWithOpcode --> SRMaskBytesSIMD + _writeData

    10. 名词解释

    PAC:代理自动配置,一个PAC文件包含一个JS形式的函数 “FindProxyForURL(url, host)” ;PAC文件中的URL可能是手工配置的,也可能是通过网页的网咯代理自发现协议(Web Proxy Autodiscovery Protocol)自动配置的;

    相关文章

      网友评论

      • 美的不像话:写的非常详细了,但是我请求的时候需要把数据添加到header里该怎么用

      本文标题:SocketRocket - facebook

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