你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS網絡編程實踐--NSStream實現TCP Socket iPhone客戶端

iOS網絡編程實踐--NSStream實現TCP Socket iPhone客戶端

編輯:IOS開發綜合

客戶端我們使用iPhone應用程序,畫面比較簡單。點擊發送按鈕,給服務器發送一些字符串過去。點擊接收按鈕就會從服務器讀取一些字符串,並且顯示在畫面上。

 


有關客戶端應用的UI部分不再介紹了,我們直接看代碼部分,Socket客戶端可以采用CFStream或NSStream實現。為了給讀者介紹更多的知識,本例我們采用NSStream實現。NSStream實現采用Objective-C語言,一些面向對象的類。

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

[cpp]
#import <CoreFoundation/CoreFoundation.h>  
 
#include <sys/socket.h>  
 
#include <netinet/in.h>  
 
  
 
#define PORT 9000  
 
  
 
@interface ViewController : UIViewController<NSStreamDelegate> 
 

 
int flag ; //操作標志 0為發送 1為接收  
 

 
  
 
@property (nonatomic, retain) NSInputStream *inputStream; 
 
@property (nonatomic, retain) NSOutputStream *outputStream; 
 
  
 
@property (weak, nonatomic) IBOutlet UILabel *message; 
 
  
 
- (IBAction)sendData:(id)sender; 
 
- (IBAction)receiveData:(id)sender; 
 
  
 
@end 

#import <CoreFoundation/CoreFoundation.h>

#include <sys/socket.h>

#include <netinet/in.h>

 

#define PORT 9000

 

@interface ViewController : UIViewController<NSStreamDelegate>

{

int flag ; //操作標志 0為發送 1為接收

}

 

@property (nonatomic, retain) NSInputStream *inputStream;

@property (nonatomic, retain) NSOutputStream *outputStream;

 

@property (weak, nonatomic) IBOutlet UILabel *message;

 

- (IBAction)sendData:(id)sender;

- (IBAction)receiveData:(id)sender;

 

@end


定義屬性inputStream和outputStream,它們輸入流NSInputStream和輸出流NSOutputStream類。它們與服務器CFStream實現中的輸入流CFReadStreamRef和輸出流CFWriteStreamRef對應的。

視圖控制器ViewController.m的初始化網絡方法initNetworkCommunication代碼:

[cpp]
 (void)initNetworkCommunication 
 

 
CFReadStreamRef readStream; 
 
CFWriteStreamRef writeStream; 
 
CFStreamCreatePairWithSocketToHost(NULL, 
 
(CFStringRef)@”192.168.1.103″, PORT, &readStream, &writeStream);   ① 
 
_inputStream = (__bridge_transfer NSInputStream *)readStream; ② 
 
_outputStream = (__bridge_transfer NSOutputStream*)writeStream;  ③ 
 
[_inputStream setDelegate:self];  ④ 
 
[_outputStream setDelegate:self];  ⑤ 
 
[_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
 
forMode:NSDefaultRunLoopMode]; ⑥ 
 
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
 
forMode:NSDefaultRunLoopMode];  ⑦ 
 
[_inputStream open];  ⑧ 
 
[_outputStream open];  ⑨ 
 

 
點擊發送和接收按鈕觸發的方法如下: 
 
/* 點擊發送按鈕  */ 
 
- (IBAction)sendData:(id)sender { 
 
flag = 0; 
 
[self initNetworkCommunication]; 
 

 
/* 點擊接收按鈕  */ 
 
- (IBAction)receiveData:(id)sender { 
 
flag = 1; 
 
[self initNetworkCommunication]; 
 

- (void)initNetworkCommunication

{

CFReadStreamRef readStream;

CFWriteStreamRef writeStream;

CFStreamCreatePairWithSocketToHost(NULL,

(CFStringRef)@”192.168.1.103″, PORT, &readStream, &writeStream);   ①

_inputStream = (__bridge_transfer NSInputStream *)readStream; ②

_outputStream = (__bridge_transfer NSOutputStream*)writeStream;  ③

[_inputStream setDelegate:self];  ④

[_outputStream setDelegate:self];  ⑤

[_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]

forMode:NSDefaultRunLoopMode]; ⑥

[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]

forMode:NSDefaultRunLoopMode];  ⑦

[_inputStream open];  ⑧

[_outputStream open];  ⑨

}

點擊發送和接收按鈕觸發的方法如下:

/* 點擊發送按鈕  */

- (IBAction)sendData:(id)sender {

flag = 0;

[self initNetworkCommunication];

}

/* 點擊接收按鈕  */

- (IBAction)receiveData:(id)sender {

flag = 1;

[self initNetworkCommunication];

}


它們都調用initNetworkCommunication方法,並設置操作標識flag,如果flag為0發送數據,flag為1接收數據。

流的狀態的變化觸發很多事件,並回調NSStreamDelegate協議中定義的方法stream:handleEvent:,其代碼如下:

[cpp]
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { 
 
NSString *event; 
 
switch (streamEvent) { 
 
case NSStreamEventNone: 
 
event = @”NSStreamEventNone”; 
 
break; 
 
case NSStreamEventOpenCompleted: 
 
event = @”NSStreamEventOpenCompleted”; 
 
break; 
 
case NSStreamEventHasBytesAvailable: 
 
event = @”NSStreamEventHasBytesAvailable”; 
 
if (flag ==1 && theStream == _inputStream) { 
 
NSMutableData *input = [[NSMutableData alloc] init]; 
 
uint8_t buffer[1024];  ① 
 
int len; 
 
while([_inputStream hasBytesAvailable]) ② 
 

 
len = [_inputStream read:buffer maxLength:sizeof(buffer)];  ③ 
 
if (len > 0) 
 

 
[input appendBytes:buffer length:len]; 
 

 

 
NSString *resultstring = [[NSString alloc] 
 
initWithData:input encoding:NSUTF8StringEncoding]; 
 
NSLog(@”接收:%@”,resultstring); 
 
_message.text = resultstring; 
 

 
break; 
 
case NSStreamEventHasSpaceAvailable: 
 
event = @”NSStreamEventHasSpaceAvailable”; 
 
if (flag ==0 && theStream == _outputStream) { 
 
//輸出  
 
UInt8 buff[] = ”Hello Server!”; ④ 
 
[_outputStream write:buff maxLength: strlen((const char*)buff)+1]; ⑤ 
 
//關閉輸出流  
 
[_outputStream close]; 
 

 
break; 
 
case NSStreamEventErrorOccurred: 
 
event = @”NSStreamEventErrorOccurred”; 
 
[self close]; ⑥ 
 
break; 
 
case NSStreamEventEndEncountered: 
 
event = @”NSStreamEventEndEncountered”; 
 
NSLog(@”Error:%d:%@”,[[theStream streamError] code], 
 
[[theStream streamError] localizedDescription]); 
 
break; 
 
default: 
 
[self close];  ⑦ 
 
event = @”Unknown”; 
 
break; 
 

 
NSLog(@”event——%@”,event); 
 

-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {

NSString *event;

switch (streamEvent) {

case NSStreamEventNone:

event = @”NSStreamEventNone”;

break;

case NSStreamEventOpenCompleted:

event = @”NSStreamEventOpenCompleted”;

break;

case NSStreamEventHasBytesAvailable:

event = @”NSStreamEventHasBytesAvailable”;

if (flag ==1 && theStream == _inputStream) {

NSMutableData *input = [[NSMutableData alloc] init];

uint8_t buffer[1024];  ①

int len;

while([_inputStream hasBytesAvailable]) ②

{

len = [_inputStream read:buffer maxLength:sizeof(buffer)];  ③

if (len > 0)

{

[input appendBytes:buffer length:len];

}

}

NSString *resultstring = [[NSString alloc]

initWithData:input encoding:NSUTF8StringEncoding];

NSLog(@”接收:%@”,resultstring);

_message.text = resultstring;

}

break;

case NSStreamEventHasSpaceAvailable:

event = @”NSStreamEventHasSpaceAvailable”;

if (flag ==0 && theStream == _outputStream) {

//輸出

UInt8 buff[] = ”Hello Server!”; ④

[_outputStream write:buff maxLength: strlen((const char*)buff)+1]; ⑤

//關閉輸出流

[_outputStream close];

}

break;

case NSStreamEventErrorOccurred:

event = @”NSStreamEventErrorOccurred”;

[self close]; ⑥

break;

case NSStreamEventEndEncountered:

event = @”NSStreamEventEndEncountered”;

NSLog(@”Error:%d:%@”,[[theStream streamError] code],

[[theStream streamError] localizedDescription]);

break;

default:

[self close];  ⑦

event = @”Unknown”;

break;

}

NSLog(@”event——%@”,event);

}


在讀取數據分支(NSStreamEventHasBytesAvailable)中,代碼第①行為讀取數據准備緩沖區,本例中設置的是1024個字節,這個大小會對流的讀取有很多的影響。第②行代碼使用hasBytesAvailable方法判斷是否流有數據可以讀,如果有可讀數據就進行循環讀取。第③行代碼使用流的read:maxLength:方法讀取數據到緩沖區,第1個參數是緩沖區對象buffer,第2個參數是讀取的緩沖區的字節長度。

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

第⑥和第⑦行代碼[self close]調用close方法關閉,close方法代碼如下:

[cpp]
-(void)close 
 

 
[_outputStream close]; 
 
[_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
 
forMode:NSDefaultRunLoopMode]; 
 
[_outputStream setDelegate:nil]; 
 
[_inputStream close]; 
 
[_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
 
forMode:NSDefaultRunLoopMode]; 
 
[_inputStream setDelegate:nil]; 
 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved