奶头挺立呻吟高潮av全片,成人试看120秒体验区,性欧美极品v,A片高潮抽搐揉捏奶头视频

網(wǎng)絡(luò)技術(shù)

包與流之間的轉(zhuǎn)換方法

時(shí)間:2024-08-31 18:15:44 網(wǎng)絡(luò)技術(shù) 我要投稿
  • 相關(guān)推薦

包與流之間的轉(zhuǎn)換方法

  引導(dǎo)語(yǔ):網(wǎng)絡(luò)傳輸中,數(shù)據(jù)包與數(shù)據(jù)流的相互轉(zhuǎn)換都有哪些方法呢?以下是小編整理的包與流之間的轉(zhuǎn)換方法,歡迎參考閱讀!

  辦法一:特殊切割符來(lái)分割包

  這種辦法粗暴簡(jiǎn)單,我們使用一個(gè)特殊字符來(lái)作為包與包之間的分隔符,不過(guò)這個(gè)分隔符要特殊,特殊到幾乎不出現(xiàn)在包的內(nèi)容當(dāng)中,否則會(huì)影響接收方切割包的過(guò)程。

  作為發(fā)送方,我們可以用如下代碼(示意用):

  #define kSeparatorChar @"¤"

  + (NSString*)encodeTextPayload:(NSString*)payload {

  NSString* str = [NSString stringWithFormat:@"%@%@", kSeparatorChar, payload];

  return str;

  }

  ¤ 就是一個(gè)非常特殊的字符,一般應(yīng)用層的文本都不會(huì)涉及到,所以可以用作我們的特殊分隔符。接收端只需要以 ¤ 為分隔符,再把數(shù)據(jù)做一次切割即可:

  + (NSString*)decodeTextPayloadString:(NSString*)str {

  NSString* payload;

  NSArray* arr = [str componentsSeparatedByString:kSeparatorChar];

  if (arr.count < 2) {

  return nil;

  }

  payload = arr[1];

  return payload;

  }

  這種做法的缺陷也是顯而易見(jiàn)的,必須嚴(yán)格要求包體中不會(huì)出現(xiàn)該特殊字符,所以這種辦法只能應(yīng)用于非常特殊的場(chǎng)景。

  辦法二:每個(gè)包都是固定長(zhǎng)度

  這種辦法也是粗暴簡(jiǎn)單,甚至不需要分隔符,每次接收方從 stream 中取出固定長(zhǎng)度的字節(jié),還原成一個(gè)包,代碼也比較簡(jiǎn)單,在 receive() 回調(diào)里,每次檢查是否達(dá)到了固定的長(zhǎng)度,是則取出固定長(zhǎng)度還原,否則繼續(xù)等待,代碼就不演示啦。

  這種做法的缺陷就更大了,會(huì)造成包體的浪費(fèi),無(wú)法適應(yīng)不同大小的包。

  辦法三:自定義協(xié)議,支持可變長(zhǎng)度的包

  之前一篇介紹自定義通訊協(xié)議的文章里,簡(jiǎn)單的提到過(guò)如何設(shè)計(jì)一個(gè)可用的協(xié)議,這里我們具體看下代碼。

  當(dāng)我們需要描述可變長(zhǎng)度的包時(shí),需要定義一個(gè) header 來(lái)詳細(xì)描述包相關(guān)的信息,比如最簡(jiǎn)單的,記錄包的長(zhǎng)度。如何記錄包的大小呢?我們可以用位操作的特性,來(lái)將應(yīng)用層的 int 值放入到包的 header 中,代碼如下(代碼摘自以前的項(xiàng)目,稍有改動(dòng)):

  - (NSData*)encodeData:(NSData*)data withHeader:(NSString*)header {

  int dataSize = (int)data.length;

  char buffer[4];

  buffer[0] = dataSize >> 24;

  buffer[1] = (dataSize << 8) >> 24;

  buffer[2] = (dataSize << 16) >> 24;

  buffer[3] = (dataSize << 24) >> 24;

  NSMutableData* packet = [NSMutableData new];

  [packet appendBytes:[header UTF8String] length:2];

  [packet appendBytes:buffer length:4];

  [packet appendData:data];

  return packet;

  }

  這是一個(gè)通用的技巧,當(dāng)我們需要在 stream 中記錄可變長(zhǎng)度的數(shù)據(jù)時(shí),都可以用這種位操作來(lái)做轉(zhuǎn)換,只需要 2 個(gè)字節(jié)的長(zhǎng)度,即可記錄長(zhǎng)達(dá) 64 KB 的數(shù)據(jù)長(zhǎng)度,4 個(gè)字節(jié)則能記錄長(zhǎng)達(dá) 4 GB 的長(zhǎng)度。

  接收方在收到 NSData 之后,可以先讀取 4 個(gè)字節(jié)的長(zhǎng)度信息,還原成 int 值,再讀取 int 值所記錄的字節(jié)數(shù),這些字節(jié)就是我們的包了,代碼如下:

  - (TDecodedData*)decodeData:(NSData*)data {

  TDecodedData* d = [TDecodedData new];

  if (data.length < 6) { //minimal packet length

  return nil;

  }

  if ([headerStr isEqualToString:kPacketStreamHeader] == true) {

  int realSize = 0;

  unsigned char buffer[4];

  [data getBytes:buffer range:NSMakeRange(2, 4)];

  realSize += buffer[0] << 24;

  realSize += buffer[1] << 16;

  realSize += buffer[2] << 8;

  realSize += buffer[3] << 0;

  if (data.length - 6 < realSize) {

  return nil;

  }

  d.header = kPacketStreamHeader;

  NSData* payloadBytes = [data subdataWithRange:NSMakeRange(6, realSize)];

  if (payloadBytes.length > 0) {

  d.decodedData = payloadBytes;

  }

  //remove from data

  int handledLength = 6 + realSize;

  NSData* nd = [NSData dataWithBytes:data.bytes + handledLength length:data.length-handledLength];

  d.handledData = nd;

  }

  return d;

  }

  上面的代碼主要是向大家展示,如何以添加 header 的方式,來(lái)記錄可變長(zhǎng)度的包體信息。如此,發(fā)送方所發(fā)送的 NSData 就和接收方所接受的 NSData 一一對(duì)應(yīng)起來(lái)了,就就不存在所謂的粘包和拆包問(wèn)題了。

  我們之所以可以對(duì)一個(gè) stream 做切分,是因?yàn)?TCP 已經(jīng)做了可靠傳輸?shù)谋WC,接收方收到的 stream 和發(fā)送方發(fā)送的 stream 嚴(yán)格一致,一個(gè)字節(jié)都不會(huì)差,所以我們只需要先讀取長(zhǎng)度值,再按長(zhǎng)度值讀取后續(xù)的數(shù)據(jù),就能把一個(gè) stream 分割成一個(gè)個(gè)的 NSData,這些分割好的 NSData 就是發(fā)送方所發(fā)送的包了。

  接收方將 stream 分割成 NSData 之后,需要進(jìn)一步將 data 反序列化成應(yīng)用層的包,這里就必須提到 google 開(kāi)源的 protobuf 了,序列化和反序列化神器,造福了無(wú)數(shù)的框架和應(yīng)用,甚至有 Objective C 的版本。

【包與流之間的轉(zhuǎn)換方法】相關(guān)文章:

C語(yǔ)言類型轉(zhuǎn)換的方法08-05

java類型的字符轉(zhuǎn)換的方法09-09

計(jì)算機(jī)進(jìn)制轉(zhuǎn)換方法06-15

java輸入數(shù)據(jù)流的方法08-19

英語(yǔ)短語(yǔ)句型轉(zhuǎn)換的方法歸納07-03

java輸入數(shù)據(jù)流的方法有哪些06-04

PHPASCII碼與字符串的相互轉(zhuǎn)換的方法08-25

php二進(jìn)制與字符串之間的相互轉(zhuǎn)換05-29

PHP數(shù)組和字符串互相轉(zhuǎn)換實(shí)現(xiàn)方法09-18

PHP 數(shù)組和字符串互相轉(zhuǎn)換實(shí)現(xiàn)方法06-28

主站蜘蛛池模板: 成武县| 黔西县| 灌云县| 廉江市| 柘荣县| 新闻| 隆回县| SHOW| 霍邱县| 获嘉县| 惠东县| 彭山县| 溧阳市| 城步| 宁乡县| 绥棱县| 石棉县| 大理市| 迁安市| 锡林郭勒盟| 榆林市| 舟曲县| 乃东县| 德昌县| 上林县| 若羌县| 留坝县| 浦北县| 上蔡县| 安溪县| 洪洞县| 庆城县| 荣昌县| 湖南省| 东海县| 措美县| 辽源市| 读书| 黔西县| 晋中市| 海兴县|