您好,欢迎来电子发烧友网! ,新用户?[免费注册]

您的位置:电子发烧友网>源码下载>通讯/手机编程>

iOS系统SRWebSocket的源码解析下

大小:0.3 MB 人气: 2017-09-25 需要积分:1

  四。 接着来讲讲数据的读和写:

  当建立连接成功后,就会循环调用这么一个方法:

  //读取http头部

  - (void)_readHTTPHeader;

  {

  if (_receivedHTTPHeaders == NULL) {

  //序列化的http消息

  _receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO);

  }

  //不停的add consumer去读数据

  [self _readUntilHeaderCompleteWithCallback:^(SRWebSocket *self, NSData *data) {

  //拼接数据,拼到头部

  CFHTTPMessageAppendBytes(_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length);

  //判断是否接受完

  if (CFHTTPMessageIsHeaderComplete(_receivedHTTPHeaders)) {

  SRFastLog(@“Finished reading headers %@”, CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_receivedHTTPHeaders)));

  [self _HTTPHeadersDidFinish];

  } else {

  //没读完递归调

  [self _readHTTPHeader];

  }

  }];

  }

  记得楼主之前写过一篇即时通讯下数据粘包、断包处理实例(基于CocoaAsyncSocket),因此抛出一个问题,WebSocket需要处理数据的断包和粘包么?

  答案是基本不需要。引用知乎上的一段回答:

  RFC规范指出,WebSocket是一个message-based的协议,它可以自动将数据分片,并且自动将分片的数据组装。

  也就是说,WebSocket的RFC标准是不会产生粘包、断包问题的。无需应用层开发人员关心缓存以及手工组装message。

  然而理想与现实的不一致:RFC规范与实现的不一致,现实当中有几个问题:

  每个message可以是一个或多个分片。message不记录长度,分片才记录长度。

  message最大的长度可以达到 9,223,372,036,854,775,807 字节,是由于Payload的数据长度有63bit的限制。

  很多WebSocket的实现其实并不按照标准的RFC实现完全,很多仅仅实现了50%就拿来用了。这就导致了,在WebSocket实现上的最大长度很难达到这个大小,于是,很多API的实现上是会有限制的,可能会限制你的发送的长度,也可能会把过长的数据直接以流式发送。

  而SRWebSocket中实现的方式上彻底解决了数据粘包,断包的可能。

  数据是通过CFStream流的方式回调回来的,每次拿到流数据,都是先放在数据缓冲区中,然后去读当前消息帧的头部,得到当前数据包的大小,然后再去创建消费者对象consumer,去读取缓冲区指定数据包大小的内容,读完才会回调给我们上层用户,所以,我们如果用SRWebSocket完全不需要考虑数据断包、粘包的问题,每次到达的数据,都是一条完整的数据。

  接着我们大概来看看这个流程:

  //读取CRLFCRLFBytes,直到回调回来

  - (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler;

  {

  [self _readUntilBytes:CRLFCRLFBytes length:sizeof(CRLFCRLFBytes) callback:dataHandler];

  }

  //读取数据 CRLFCRLFBytes,边界符

  - (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler;

  {

  // TODO optimize so this can continue from where we last searched

  //消费者需要消费的数据大小

  stream_scanner consumer = ^size_t(NSData *data) {

  __block size_t found_size = 0;

  __block size_t match_count = 0;

  //得到数据长度

  size_t size = data.length;

  //得到数据指针

  const unsigned char *buffer = data.bytes;

  for (size_t i = 0; i 《 size; i++ ) {

  //匹配字符

  if (((const unsigned char *)buffer)[i] == ((const unsigned char *)bytes)[match_count]) {

  //匹配数+1

  match_count += 1;

  //如果匹配了

  if (match_count == length) {

  //读取数据长度等于 i+ 1

  found_size = i + 1;

  break;

  }

  } else {

  match_count = 0;

  }

  }

  //返回要读取数据的长度,没匹配成功就是0

  return found_size;

非常好我支持^.^

(0) 0%

不好我反对

(0) 0%

      发表评论

      用户评论
      评价:好评中评差评

      发表评论,获取积分! 请遵守相关规定!