Socket通信(一)
// // ViewController.m // Socket1 // // Created by 阿仁欧巴 on 16/5/7. // Copyright © 2016年 aren. All rights reserved. // #import "ViewController.h" @interface ViewController () <NSStreamDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate> { NSInputStream *_inputStream; NSOutputStream *_outStream; } //@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomViewConstraint; @property (weak, nonatomic) IBOutlet UIView *commentView;//发送消息的文本框的父视图,根据键盘的出现与否设置它的frame @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong) NSMutableArray *chatMsgs; //聊天消息数组 @end @implementation ViewController - (NSMutableArray *)chatMsgs { if (!_chatMsgs) { _chatMsgs = [NSMutableArray array]; } return _chatMsgs; } //连接服务器的按钮 - (IBAction)connect:(id)sender { //1.获取服务器的IP地址和端口号 NSString *host = @"127.0.0.1"; int port = 8080; //2.获取输入输出流 CFReadStreamRef readRef; CFWriteStreamRef writeRef; //3.将C语言对象转换成OC对象 _inputStream = (__bridge NSInputStream *)(readRef); _outStream = (__bridge NSOutputStream *)(writeRef); //4.建立连接 CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readRef, &writeRef); //5.设置代理 _inputStream.delegate = self; _outStream.delegate = self; #pragma mark ---如果不添加到主循环,代理方法可能不执行---- //6.扔进主循环 [_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_outStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; //7.打开输入输出流 [_inputStream open]; [_outStream open]; #pragma mark ---链接结束时,需要将输入输出流从主循环中移除 并且关闭输入输出流, 在代理方法中执行---- } //登录按钮 - (IBAction)login:(id)sender { //登陆的指令 NSString *loginString = @"iam:arenouba"; //转换成NSData类型的 NSData *data = [loginString dataUsingEncoding:NSUTF8StringEncoding]; //输出流发送登录数据给服务器 [_outStream write:data.bytes maxLength:data.length]; } #pragma mark ---输入流 读取 服务器 返回的数据 XMPP 已经封装好了,不用我们处理--- - (void)readData { //建立一个缓冲区,可以放1024个字节 uint8_t buf[1024]; // len 返回实际存放的字节数 NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)]; //sizeof(buf) //把字节转化成字符串 NSData *data = [NSData dataWithBytes:buf length:len]; //转换成字符串 从服务器接收到的数据 NSString *recieveString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //刷新数据 [self reloadDataWithText:recieveString]; NSLog(@"%@",recieveString); } #pragma mark --- 点击发送按钮时 获取文本输入框的文字,并刷新tableView --- - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSString *text = textField.text; NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding]; [self reloadDataWithText:text]; //发送数据给服务器 [_outStream write:data.bytes maxLength:data.length]; //发送完成后,清空文本框 textField.text = nil; return YES; } - (void)reloadDataWithText:(NSString *)text { //添加文本输入框的数据到消息数组中 [self.chatMsgs addObject:text]; //刷新 [self.tableView reloadData]; //发送一条消息,使tableView跟着向上滚动一行 NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:self.chatMsgs.count - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } #pragma mark --- 将要拖动时,键盘消失--- - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { [self.view endEditing:YES]; } #pragma mark ----NSStreamDelegate ----- - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { #warning mark --- 这是在主线程中执行的 NSLog(@"%@",[NSThread currentThread]); /* NSStreamEventNone = 0, NSStreamEventOpenCompleted = 1UL << 0, 输入输出流打开完成 NSStreamEventHasBytesAvailable = 1UL << 1, 有字节可读 NSStreamEventHasSpaceAvailable = 1UL << 2, 可以发送字节 NSStreamEventErrorOccurred = 1UL << 3, 连接出现了错误 NSStreamEventEndEncountered = 1UL << 4 连接结束 */ switch (eventCode) { case NSStreamEventOpenCompleted: NSLog(@" 输入输出流打开完成"); break; case NSStreamEventHasBytesAvailable: NSLog(@"有字节可读"); break; case NSStreamEventHasSpaceAvailable: NSLog(@"可以发送字节"); break; case NSStreamEventErrorOccurred: NSLog(@"连接错误"); break; case NSStreamEventEndEncountered: NSLog(@"连接结束"); //关闭输入输出流 [_inputStream close]; [_outStream close]; //从主循环移除 [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_outStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; break; default: break; } } - (void)viewDidLoad { [super viewDidLoad]; //监听键盘将要出现时 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChang:) name:UIKeyboardWillChangeFrameNotification object:nil]; //监听键盘将要隐藏时 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHidden:) name:UIKeyboardWillHideNotification object:nil]; self.tableView.delegate = self; self.tableView.dataSource = self; [self.view insertSubview:_tableView atIndex:0]; // Do any additional setup after loading the view, typically from a nib. } - (void)keyboardWillChang:(NSNotification *)noti { NSLog(@"%@",noti.userInfo); //键盘结束的y值 CGRect kbEndFrame = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; [UIView animateWithDuration:[noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{ self.commentView.transform = CGAffineTransformMakeTranslation(0, -kbEndFrame.size.height); }]; } - (void)keyboardWillHidden:(NSNotification *)noti { //键盘结束的y值 [UIView animateWithDuration:[noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{ self.commentView.transform = CGAffineTransformIdentity; }]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.chatMsgs.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
cell.textLabel.text = self.chatMsgs[indexPath.row]; return cell; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end