温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

iOS网络编程实践--NSStream实现TCP Socket iPhone客户端

发布时间:2020-06-15 17:25:46 阅读:3700 作者:tony关东升 栏目:移动开发
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

客户端我们使用iPhone应用程序,画面比较简单。点击发送按钮,给服务器发送一些字符串过去。点击接收按钮就会从服务器读取一些字符串,并且显示在画面上。

iOS网络编程实践--NSStream实现TCP Socket iPhone客户端

有关客户端应用的UI部分不再介绍了,我们直接看代码部分,Socket客户端可以采用CFStream或NSStream实现,CFStream 实现方式与服务器端基本一样。为了给读者介绍更多的知识,本例我们采用NSStream实现。NSStream实现采用Objective-C语言,一些 面向对象的类。

下面我们看看客户端视图控制器ViewController.h

#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代码:

- (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,如果flag0发送数据,flag1接收数据。

流的状态的变化触发很多事件,并回调NSStreamDelegate协议中定义的方法stream:handleEvent:,其代码如下:

-(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方法代码如下:

-(void)close  {  [_outputStream close];  [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]  forMode:NSDefaultRunLoopMode];  [_outputStream setDelegate:nil];  [_inputStream close];  [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]  forMode:NSDefaultRunLoopMode];  [_inputStream setDelegate:nil];  } 

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×