iOS 基于Socket 的 C/S 网络通信结构(下一个)
以前实现简单 Server 程序,服务端通过 void WriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void* clientCallBackInfo) 函数向client发送“你好。client!”的消息,假设client接收成功的话就会显示“你好。client!
”。须要显示服务端发送过来的消息。那么就须要定义一个UILabel输出口(IBOutlet)来显示消息;client还须要加入两个button,一个用来接收服务端消息的动作事件方法 receiveData:和发送client“收到啦,服务端”消息的动作事件方法 sendData:;加入关联就能够了,比較简单,以下来看一下详细实现的代码:
ViewController.h
#import <UIKit/UIKit.h> #import <CoreFoundation/CoreFoundation.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8734 //将端口设置为8734。能够依据详细情况改变 @interface ViewController : UIViewController<NSStreamDelegate> { int flag ; //操作标志 0为发送 1为接收 } @property (nonatomic, retain) NSInputStream *inputStream; @property (nonatomic, retain) NSOutputStream *outputStream; @property (weak, nonatomic) IBOutlet UILabel *message; //在client显示来自服务端的消息 - (IBAction)sendData:(id)sender; //发送client的消息 - (IBAction)receiveData:(id)sender; //接收来自服务端的消息 @endViewController.m
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } //初始化client网络连接 - (void)initNetworkCommunication { CFReadStreamRef readStream; CFWriteStreamRef writeStream; //这里须要填写 IP 地址,依据自己路由能够用的 IP来定,这里是192.168.1.103,假设不知道能够下载 IP 扫描器 CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.1.103", PORT, &readStream, &writeStream); self.inputStream = (__bridge_transfer NSInputStream *)readStream; //将CFStream对象转化为NSStream对象 self.outputStream = (__bridge_transfer NSOutputStream *)writeStream; //将CFStream对象转化为NSStream对象 [self.inputStream setDelegate:self]; [self.outputStream setDelegate:self]; [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; //NSStream 方法 scheduleInRunLoop: 设置 Run Loop [self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [self.inputStream open]; //NSStream 的 open 方法来打开数据流对象 [self.outputStream open]; } //关闭数据流操作 -(void)close { [self.outputStream close]; [self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [self.outputStream setDelegate:nil]; [self.inputStream close]; [self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [self.inputStream setDelegate:nil]; } //从client发送数据事件方法 - (IBAction)sendData:(id)sender { flag = 0; //表示发送 [self initNetworkCommunication]; } //从服务端接收数据事件方法 - (IBAction)receiveData:(id)sender { flag = 1; //表示接收 [self initNetworkCommunication]; } -(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[2048]; //读取数据准备缓冲区,本例中设置的是2048字节,这个大小会对流的读取有非常大影响 int len; while([self.inputStream hasBytesAvailable]) { len = [self.inputStream read:buffer maxLength:sizeof(buffer)]; //读取数据到缓冲区 if (len > 0) { [input appendBytes:buffer length:len]; } } NSString *resultstring = [[NSString alloc] initWithData:input encoding:NSUTF8StringEncoding]; NSLog(@"接收:%@",resultstring); self.message.text = resultstring; } break; case NSStreamEventHasSpaceAvailable: //这个流能够接收数据的写入,在写数据时使用 event = @"NSStreamEventHasSpaceAvailable"; if (flag ==0 && theStream == _outputStream) { //输出 UInt8 buff[] = "收到啦,服务端。"; //向服务端发送的消息 [self.outputStream write:buff maxLength: strlen((const char*)buff)+1]; //向服务端写入数据方法 //必须关闭输出流否则,server端一直读取不会停止。 [self.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; } } @end从代码能够知道。client採用的是 APPLE 自家的 NSStream 来实现的,都是比較简单的基本数据流操作。
如有哪些不正确的地方,欢迎指出!
版权声明:本文博主原创文章,博客,未经同意不得转载。