<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [深入淺出Cocoa]iOS網(wǎng)絡(luò)編程之NSStream

      [深入淺出Cocoa]iOS網(wǎng)絡(luò)編程之NSStream

      羅朝輝 (http://www.rzrgm.cn/kesalin/)

      本文遵循“署名-非商業(yè)用途-保持一致”創(chuàng)作公用協(xié)議
       

      一,NSStream簡介

      首先來回顧下。在前文《[深入淺出Cocoa]iOS網(wǎng)絡(luò)編程之Socket》中,提到iOS網(wǎng)絡(luò)編程層次模型分為三層:
      • Cocoa層:NSURL,Bonjour,Game Kit,WebKit
      • Core Foundation層:基于 C 的 CFNetwork 和 CFNetServices
      • OS層:基于 C 的 BSD socket
      前文《iOS網(wǎng)絡(luò)編程之Socket》 和《iOS網(wǎng)絡(luò)編程之CFNetwork》 講了最底層的 socket 和Core Foundation層的 CFNetwork,本文將介紹位于 Cocoa 中的 NSStream。NSStream 其實只是用 Objective-C 對 CFNetwork 的簡單封裝,它使用名為 NSStreamDelegate 的協(xié)議來實現(xiàn) CFNetwork 中的回調(diào)函數(shù)的作用,同樣,runloop 也與 NSStream 結(jié)合的很好。NSStream 有兩個實體類:NSInputStream 和 NSOutputStream,分別對應 CFNetwork 中的 CFReadStream 和 CFWriteStream。
       
      本文示例代碼請查看:

      二,NSStream 類接口簡介

      NSStream 類有如下接口:

      - (void)open;

      - (void)close;

      - (id <NSStreamDelegate>)delegate;

      - (void)setDelegate:(id <NSStreamDelegate>)delegate;

      - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;

      - (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;

      - (NSStreamStatus)streamStatus;

      - (NSError *)streamError;

      NSStream 的一些接口與 CFNetwork 類似,如打開,關(guān)閉,獲取狀態(tài)和錯誤信息,以及和 runloop 結(jié)合等在這里就不再重復了。前面提到 NSStream 是通過 NSStreamDelegate 來實現(xiàn) CFNetwork 中的回調(diào)函數(shù),這個可選的協(xié)議只有一個接口:

      - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode;

      NSStreamEvent 是一個流事件枚舉:

      typedef NS_OPTIONS(NSUInteger, NSStreamEvent) {

          NSStreamEventNone = 0,

          NSStreamEventOpenCompleted = 1UL << 0,

          NSStreamEventHasBytesAvailable = 1UL << 1,

          NSStreamEventHasSpaceAvailable = 1UL << 2,

          NSStreamEventErrorOccurred = 1UL << 3,

          NSStreamEventEndEncountered = 1UL << 4

      };

      這些事件枚舉的含義也和 CFNetwork 中的 CFStreamEventType 類似,在此也就不再重復了。

      NSInputStream 類有如下接口:

      - (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len;
      從流中讀取數(shù)據(jù)到 buffer 中,buffer 的長度不應少于 len,該接口返回實際讀取的數(shù)據(jù)長度(該長度最大為 len)。

      - (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len;
      獲取當前流中的數(shù)據(jù)以及大小,注意 buffer 只在下一個流操作之前有效。

      - (BOOL)hasBytesAvailable;
      檢查流中是否還有數(shù)據(jù)。

      NSOutputStream 類有如下接口:

      - (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)len;
      將 buffer 中的數(shù)據(jù)寫入流中,返回實際寫入的字節(jié)數(shù)。

      - (BOOL)hasSpaceAvailable;
      檢查流中是否還有可供寫入的空間。

      從這些接口可以看出,NSStream 真的就是 CFNetwork 上的一層簡單的 Objective-C 封裝。但 iOS 中的 NSStream 不支持 NShost,這是一個缺陷,蘋果也意識到這問題了(http://developer.apple.com/library/ios/#qa/qa1652/_index.html),我們可以通過 NSStream 的擴展函數(shù)來實現(xiàn)該功能:

      @implementation NSStream(StreamsToHost)
      
      + (void)getStreamsToHostNamed:(NSString *)hostName
                               port:(NSInteger)port
                        inputStream:(out NSInputStream **)inputStreamPtr
                       outputStream:(out NSOutputStream **)outputStreamPtr
      {
          CFReadStreamRef     readStream;
          CFWriteStreamRef    writeStream;
          
          assert(hostName != nil);
          assert( (port > 0) && (port < 65536) );
          assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) );
          
          readStream = NULL;
          writeStream = NULL;
          
          CFStreamCreatePairWithSocketToHost(
                                             NULL,
                                             (__bridge CFStringRef) hostName,
                                             port,
                                             ((inputStreamPtr  != NULL) ? &readStream : NULL),
                                             ((outputStreamPtr != NULL) ? &writeStream : NULL)
                                             );
          
          if (inputStreamPtr != NULL) {
              *inputStreamPtr  = CFBridgingRelease(readStream);
          }
      
          if (outputStreamPtr != NULL) {
              *outputStreamPtr = CFBridgingRelease(writeStream);
          }
      }
      
      @end

       

      三,客戶端示例代碼

      與前面的示例類似,在這里我只演示客戶端示例。同樣,我們也在一個后臺線程中啟動網(wǎng)絡(luò)操作:

          NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", serverHost, serverPort]];
          NSThread * backgroundThread = [[NSThread alloc] initWithTarget:self
                                                                selector:@selector(loadDataFromServerWithURL:)
                                                                  object:url];
          [backgroundThread start];

      然后在 loadDataFromServerWithURL 中創(chuàng)建 NSInputStream,并設(shè)置其 delegate,將其加入到 run-loop 的事件源中,然后打開流,運行 runloop:

      - (void)loadDataFromServerWithURL:(NSURL *)url
      {
          NSInputStream * readStream;
          [NSStream getStreamsToHostNamed:[url host]
                                     port:[[url port] integerValue]
                              inputStream:&readStream
                             outputStream:NULL];
          
          [readStream setDelegate:self];
          [readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
          [readStream open];
          
          [[NSRunLoop currentRunLoop] run];
      }

      因為我們將 KSNSStreamViewController 當作 NSInputStream 的 delegate,因此要在 KSNSStreamViewController 中實現(xiàn)該 delgate:

      #pragma mark NSStreamDelegate
      
      - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
      {
          NSLog(@" >> NSStreamDelegate in Thread %@", [NSThread currentThread]);
          
          switch (eventCode) {
              case NSStreamEventHasBytesAvailable: {
                  if (_receivedData == nil) {
                      _receivedData = [[NSMutableData alloc] init];
                  }
                  
                  uint8_t buf[kBufferSize];
                  int numBytesRead = [(NSInputStream *)stream read:buf maxLength:kBufferSize];
                  
                  if (numBytesRead > 0) {
                      [self didReceiveData:[NSData dataWithBytes:buf length:numBytesRead]];
                      
                  } else if (numBytesRead == 0) {
                      NSLog(@" >> End of stream reached");
                      
                  } else {
                      NSLog(@" >> Read error occurred");
                  }
                  
                  break;
              }
                  
              case NSStreamEventErrorOccurred: {
                  NSError * error = [stream streamError];
                  NSString * errorInfo = [NSString stringWithFormat:@"Failed while reading stream; error '%@' (code %d)", error.localizedDescription, error.code];
                  
                  [self cleanUpStream:stream];
                  
                  [self networkFailedWithErrorMessage:errorInfo];
              }
                  
              case NSStreamEventEndEncountered: {
                  
                  [self cleanUpStream:stream];
                  
                  [self didFinishReceivingData];
      
                  break;
              }
                  
              default:
                  break;
          }
      }

      當數(shù)據(jù)讀取完畢或者讀取失敗時,調(diào)用 cleanUpStream 方法來關(guān)閉流:

      - (void)cleanUpStream:(NSStream *)stream
      {
          [stream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
          [stream close];
          
          stream = nil;
      }

       

      四,結(jié)語

      通過上面的示例演示,我們可以看到 NSStream 只是用 Objective-C 對 CFNetwork 的一層簡單封裝,但確實大大方便了我們使用 socket 進行編程,因此在大多數(shù)情況下,我們都應該優(yōu)先使用 NSStream 進行 socket 編程。

       

      posted @ 2013-04-29 20:10  飄飄白云  閱讀(6111)  評論(0)    收藏  舉報
      本博客遵循 Creative Commons License “署名-非商業(yè)用途-保持一致”創(chuàng)作共用協(xié)議。 與我聯(lián)系
      主站蜘蛛池模板: 国产天美传媒性色av高清| 国产乱码1卡二卡3卡四卡5| 人妻中文字幕精品一页| 野外做受三级视频| 亚洲 小说区 图片区 都市| 永久免费观看美女裸体的网站| 无码激情亚洲一区| 久激情内射婷内射蜜桃| 亚洲AV成人无码精品电影在线| 国产婷婷综合在线视频| 精品午夜福利在线视在亚洲| 亚洲十八禁一区二区三区| 国产视频最新| 久久婷婷成人综合色| 国产亚洲亚洲国产一二区| 自拍亚洲一区欧美另类| 国产av一区二区麻豆熟女| 亚洲欧美日韩综合在线丁香| 亚洲av永久无码精品漫画| 久久96热在精品国产高清| 在线看无码的免费网站| 亚洲成人av在线高清| 精品国产粉嫩一区二区三区| 久久精品国产www456c0m| 小伙无套内射老熟女精品| 亚洲国产一区二区三区最新| 在线观看国产成人av天堂| 日韩乱码人妻无码中文字幕视频| 蒲江县| 99久久精品看国产一区| 亚洲欧美日韩成人一区| 久久中文字幕日韩无码视频| 久久热这里只有精品最新| 日韩无人区码卡1卡2卡| 亚洲午夜理论无码电影| 四虎精品国产永久在线观看| 亚洲国产一区二区三区最新| 91福利一区福利二区| 日本欧美一区二区三区在线播放| 国模肉肉视频一区二区三区| 99视频偷窥在线精品国自产拍|