iOS socket编程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS socket编程相关的知识,希望对你有一定的参考价值。
// // ViewController.m // socket // // Created by emerys on 16/3/2. // Copyright © 2016年 Emerys. All rights reserved. // #import "ViewController.h" #warning 0000前面四位为消息长度,后接消息,最后以#结束 @interface ViewController ()<NSStreamDelegate,UITableViewDataSource> { // 输入流 NSInputStream *inputStream; // 输出流 NSOutputStream *outputStream; } // 用以存储聊天记录,键值为 client_date/service_date @property (nonatomic,strong) NSMutableArray *history; @property (nonatomic,copy) NSString *msg; @property (weak, nonatomic) IBOutlet UITextField *inputTextField; @property (weak, nonatomic) IBOutlet UIButton *sendMsgButton; @property (weak, nonatomic) IBOutlet UITableView *historyTableView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self loadHistory]; self.historyTableView.dataSource = self; [self connect]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /** * @brief 懒加载字典 */ -(NSMutableArray *)history{ if (!_history) { _history = [NSMutableArray array]; } return _history; } /** * @brief 开启链接 */ -(void)connect{ // 1.建立连接 NSString *host = @"119.29.65.70"; int port = 9868; // 定义C语言输入输出流 CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream); // 把C语言的输入输出流转化成OC对象 inputStream = (__bridge NSInputStream *)(readStream); outputStream = (__bridge NSOutputStream *)(writeStream); // 设置代理 inputStream.delegate = self; outputStream.delegate = self; // 把输入输入流添加到主运行循环 // 不添加主运行循环 代理有可能不工作 [inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // 打开输入输出流 [inputStream open]; [outputStream open]; } /** * @brief 开启输入/出流监听 */ -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ switch (eventCode) { case NSStreamEventNone:{ } break; case NSStreamEventOpenCompleted:{ // 打开 // [self showAlertMessage:@"连接服务器成功"]; NSLog(@"ok"); } break; case NSStreamEventHasBytesAvailable:{ // 有数据可读 [self readData]; } break; case NSStreamEventHasSpaceAvailable:{ // 可发 if (self.msg) { [self writeData]; } } break; case NSStreamEventErrorOccurred:{ // 链接错误,那么重新链接 [self connect]; } break; case NSStreamEventEndEncountered:{ // 结束链接,关闭流,从主运行循环移开 [inputStream close]; [outputStream close]; [inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } break; default: break; } } /** * @brief 读取数据 */ -(void)readData{ // 设置1024字节的缓冲区 uint8_t buf[1024]; NSInteger length = [inputStream read:buf maxLength:1024]; if (length > 0) { NSData *data = [NSData dataWithBytes:buf length:length]; #warning 在此编码方式不同可能会引起str为空,添加进数组时程序崩溃 // gb2312 NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingGB_18030_2000); NSString *str = [[NSString alloc] initWithData:data encoding:encoding]; // NSLog(@"%@",str); [self.history addObject:str]; [self.historyTableView reloadData]; [self saveData]; } } /** * @brief 发送数据 */ -(void)writeData{ NSString *msg = self.msg; NSString *head; NSUInteger msgLength = msg.length; // 超出最大限制,或没有数据, 则不发 if (!msgLength && msgLength >= 10000) { [self showAlertMessage:@"您发送的数据长度超出限度,请重新编辑"]; }else{ if (msgLength < 10) { head = [NSString stringWithFormat:@"000%li",msgLength]; }else if(msgLength >= 10 && msgLength < 100){ head = [NSString stringWithFormat:@"00%li",msgLength]; }else if (msgLength >= 100 && msgLength < 1000){ head = [NSString stringWithFormat:@"0%li",msgLength]; }else if (msgLength >= 1000 && msgLength < 10000){ head = [NSString stringWithFormat:@"%li",msgLength]; } NSString *str = [NSString stringWithFormat:@"%@%@#",head,msg]; NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; [outputStream write:data.bytes maxLength:data.length]; self.msg = nil; [self.history addObject:msg]; [self.historyTableView reloadData]; [self saveData]; } } /** * @brief 显示一些提示信息 * @param msg 表示将要显示的信息 */ -(void)showAlertMessage:(NSString *)msg{ __block UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:msg preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [alert dismissViewControllerAnimated:YES completion:nil]; alert = nil; }]; [alert addAction:action]; [self presentViewController:alert animated:YES completion:nil]; } /** * @brief 发送数据按钮回调 */ - (IBAction)senMessage:(id)sender { NSString *msg = self.inputTextField.text; // NSString *head; NSUInteger msgLength = msg.length; // 超出最大限制或没有数据, 则不发 if (!msgLength && msgLength >= 10000) { [self showAlertMessage:@"您发送的数据长度超出限度,请重新编辑"]; }else{ self.msg = msg; [self stream:outputStream handleEvent:NSStreamEventHasSpaceAvailable]; } } #pragma mark 数据源 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [self.history count]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } NSString *str = self.history[indexPath.row]; cell.textLabel.text = str; return cell; } /** * @brief 检测文件是否存在 */ -(BOOL)checkFile{ // NSString *dPath = [NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject]; NSString *home = NSHomeDirectory(); NSString *path = [home stringByAppendingPathComponent:@"documents/history.plist"]; NSFileManager *manager = [NSFileManager defaultManager]; return [manager fileExistsAtPath:path]; } /** * @brief 保存数据到本地 */ -(void)saveData{ if (self.history.count) { NSString *home = NSHomeDirectory(); NSString *path = [home stringByAppendingPathComponent:@"documents/history.plist"]; if([self.history writeToFile:path atomically:YES]){ NSLog(@"save ok"); }else{ NSLog(@"save error"); } } } /** * @brief 读取历史数据 */ -(void)loadHistory{ NSString *home = NSHomeDirectory(); NSString *path = [home stringByAppendingPathComponent:@"documents/history.plist"]; NSArray *array = [NSArray arrayWithContentsOfFile:path]; if (array.count) { [self.history addObjectsFromArray:array]; [self.historyTableView reloadData]; } } @end
以上是关于iOS socket编程的主要内容,如果未能解决你的问题,请参考以下文章