溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

iOS網(wǎng)絡(luò)編程實(shí)踐--NSStream實(shí)現(xiàn)TCP Socket iPhone客戶端

發(fā)布時(shí)間:2020-06-15 17:25:46 來(lái)源:網(wǎng)絡(luò) 閱讀:3686 作者:tony關(guān)東升 欄目:移動(dòng)開(kāi)發(fā)

客戶端我們使用iPhone應(yīng)用程序,畫(huà)面比較簡(jiǎn)單。點(diǎn)擊發(fā)送按鈕,給服務(wù)器發(fā)送一些字符串過(guò)去。點(diǎn)擊接收按鈕就會(huì)從服務(wù)器讀取一些字符串,并且顯示在畫(huà)面上。

 

iOS網(wǎng)絡(luò)編程實(shí)踐--NSStream實(shí)現(xiàn)TCP Socket iPhone客戶端

有關(guān)客戶端應(yīng)用的UI部分不再介紹了,我們直接看代碼部分,Socket客戶端可以采用CFStream或NSStream實(shí)現(xiàn),CFStream 實(shí)現(xiàn)方式與服務(wù)器端基本一樣。為了給讀者介紹更多的知識(shí),本例我們采用NSStream實(shí)現(xiàn)。NSStream實(shí)現(xiàn)采用Objective-C語(yǔ)言,一些 面向?qū)ο蟮念?lèi)。

下面我們看看客戶端視圖控制器ViewController.h

 

  1. #import <CoreFoundation/CoreFoundation.h> 
  2.  
  3. #include <sys/socket.h> 
  4.  
  5. #include <netinet/in.h> 
  6.  
  7.   
  8.  
  9. #define PORT 9000 
  10.  
  11.   
  12.  
  13. @interface ViewController : UIViewController<NSStreamDelegate> 
  14.  
  15.  
  16. int flag ; //操作標(biāo)志 0為發(fā)送 1為接收 
  17.  
  18.  
  19.   
  20.  
  21. @property (nonatomic, retain) NSInputStream *inputStream; 
  22.  
  23. @property (nonatomic, retain) NSOutputStream *outputStream; 
  24.  
  25.   
  26.  
  27. @property (weak, nonatomic) IBOutlet UILabel *message; 
  28.  
  29.   
  30.  
  31. - (IBAction)sendData:(id)sender; 
  32.  
  33. - (IBAction)receiveData:(id)sender; 
  34.  
  35.   
  36.  
  37. @end 

定義屬性inputStream和outputStream,它們輸入流NSInputStream和輸出流NSOutputStream類(lèi)。它們與服務(wù)器CFStream實(shí)現(xiàn)中的輸入流CFReadStreamRef和輸出流CFWriteStreamRef對(duì)應(yīng)的。

視圖控制器ViewController.m的初始化網(wǎng)絡(luò)方法initNetworkCommunication代碼:

 

  1. - (void)initNetworkCommunication 
  2.  
  3.  
  4. CFReadStreamRef readStream; 
  5.  
  6. CFWriteStreamRef writeStream; 
  7.  
  8. CFStreamCreatePairWithSocketToHost(NULL, 
  9.  
  10. (CFStringRef)@”192.168.1.103″, PORT, &readStream, &writeStream);   ① 
  11.  
  12. _inputStream = (__bridge_transfer NSInputStream *)readStream; ② 
  13.  
  14. _outputStream = (__bridge_transfer NSOutputStream*)writeStream;  ③ 
  15.  
  16. [_inputStream setDelegate:self];  ④ 
  17.  
  18. [_outputStream setDelegate:self];  ⑤ 
  19.  
  20. [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
  21.  
  22. forMode:NSDefaultRunLoopMode]; ⑥ 
  23.  
  24. [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
  25.  
  26. forMode:NSDefaultRunLoopMode];  ⑦ 
  27.  
  28. [_inputStream open];  ⑧ 
  29.  
  30. [_outputStream open];  ⑨ 
  31.  

點(diǎn)擊發(fā)送和接收按鈕觸發(fā)的方法如下:

 

  1. /* 點(diǎn)擊發(fā)送按鈕  */ 
  2.  
  3. - (IBAction)sendData:(id)sender { 
  4.  
  5. flag = 0; 
  6.  
  7. [self initNetworkCommunication]; 
  8.  
  9.  
  10. /* 點(diǎn)擊接收按鈕  */ 
  11.  
  12. - (IBAction)receiveData:(id)sender { 
  13.  
  14. flag = 1; 
  15.  
  16. [self initNetworkCommunication]; 
  17.  

它們都調(diào)用initNetworkCommunication方法,并設(shè)置操作標(biāo)識(shí)flag,如果flag0發(fā)送數(shù)據(jù),flag1接收數(shù)據(jù)。

流的狀態(tài)的變化觸發(fā)很多事件,并回調(diào)NSStreamDelegate協(xié)議中定義的方法stream:handleEvent:,其代碼如下:

 

  1. -(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { 
  2.  
  3. NSString *event; 
  4.  
  5. switch (streamEvent) { 
  6.  
  7. case NSStreamEventNone: 
  8.  
  9. event = @”NSStreamEventNone”; 
  10.  
  11. break
  12.  
  13. case NSStreamEventOpenCompleted: 
  14.  
  15. event = @”NSStreamEventOpenCompleted”; 
  16.  
  17. break
  18.  
  19. case NSStreamEventHasBytesAvailable: 
  20.  
  21. event = @”NSStreamEventHasBytesAvailable”; 
  22.  
  23. if (flag ==1 && theStream == _inputStream) { 
  24.  
  25. NSMutableData *input = [[NSMutableData alloc] init]; 
  26.  
  27. uint8_t buffer[1024];  ① 
  28.  
  29. int len; 
  30.  
  31. while([_inputStream hasBytesAvailable]) ② 
  32.  
  33.  
  34. len = [_inputStream read:buffer maxLength:sizeof(buffer)];  ③ 
  35.  
  36. if (len > 0) 
  37.  
  38.  
  39. [input appendBytes:buffer length:len]; 
  40.  
  41.  
  42.  
  43. NSString *resultstring = [[NSString alloc] 
  44.  
  45. initWithData:input encoding:NSUTF8StringEncoding]; 
  46.  
  47. NSLog(@”接收:%@”,resultstring); 
  48.  
  49. _message.text = resultstring; 
  50.  
  51.  
  52. break
  53.  
  54. case NSStreamEventHasSpaceAvailable: 
  55.  
  56. event = @”NSStreamEventHasSpaceAvailable”; 
  57.  
  58. if (flag ==0 && theStream == _outputStream) { 
  59.  
  60. //輸出 
  61.  
  62. UInt8 buff[] = ”Hello Server!”; ④ 
  63.  
  64. [_outputStream write:buff maxLength: strlen((const char*)buff)+1]; ⑤ 
  65.  
  66. //關(guān)閉輸出流 
  67.  
  68. [_outputStream close]; 
  69.  
  70.  
  71. break
  72.  
  73. case NSStreamEventErrorOccurred: 
  74.  
  75. event = @”NSStreamEventErrorOccurred”; 
  76.  
  77. [self close]; ⑥ 
  78.  
  79. break
  80.  
  81. case NSStreamEventEndEncountered: 
  82.  
  83. event = @”NSStreamEventEndEncountered”; 
  84.  
  85. NSLog(@”Error:%d:%@”,[[theStream streamError] code], 
  86.  
  87. [[theStream streamError] localizedDescription]); 
  88.  
  89. break
  90.  
  91. default
  92.  
  93. [self close];  ⑦ 
  94.  
  95. event = @”Unknown”; 
  96.  
  97. break
  98.  
  99.  
  100. NSLog(@”event——%@”,event); 
  101.  

在讀取數(shù)據(jù)分支(NSStreamEventHasBytesAvailable)中,代碼第①行為讀取數(shù)據(jù)準(zhǔn)備緩沖區(qū),本例中設(shè)置的是1024個(gè)字節(jié),這個(gè)大小會(huì)對(duì)流的讀取有很多的影響。第②行代碼使用hasBytesAvailable方法判斷是否流有數(shù)據(jù)可以讀,如果有可讀數(shù)據(jù)就進(jìn)行循環(huán)讀取。第③行代碼使用流的read:maxLength:方法讀取數(shù)據(jù)到緩沖區(qū),第1個(gè)參數(shù)是緩沖區(qū)對(duì)象buffer,第2個(gè)參數(shù)是讀取的緩沖區(qū)的字節(jié)長(zhǎng)度。

在寫(xiě)入數(shù)據(jù)分支(NSStreamEventHasSpaceAvailable)中,代碼第④行是要寫(xiě)入的數(shù)據(jù),第⑤行代碼 [_outputStream write:buff maxLength: strlen((const char*)buff)+1]是寫(xiě)如數(shù)據(jù)方 法。

第⑥和第⑦行代碼[self close]調(diào)用close方法關(guān)閉,close方法代碼如下:

 

  1. -(void)close 
  2.  
  3.  
  4. [_outputStream close]; 
  5.  
  6. [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
  7.  
  8. forMode:NSDefaultRunLoopMode]; 
  9.  
  10. [_outputStream setDelegate:nil]; 
  11.  
  12. [_inputStream close]; 
  13.  
  14. [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
  15.  
  16. forMode:NSDefaultRunLoopMode]; 
  17.  
  18. [_inputStream setDelegate:nil]; 
  19.  
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI