zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    【随感】我真的很敬重你,只是你不知道。。。。。
    【diary】智慧的贪婪
    【随感】看老科和当当的回眸相视
    【转载】清华毕业致辞:从容行走于无人知晓的荒原,欣赏并创造别样的风景
    【随感】不要以为自己不足轻重而放任自己做一些事或一些话。你的不在意,才会影响到别人也不在意你。
    【随感】我觉得,世界上最美好的乐器是钢琴和架子鼓
    【技术】HTML5 canvas clock(1)
    【随感】youngLaker,fighting!
    转发公司招聘
    DBCC DBREINDEX
  • 原文地址:https://www.cnblogs.com/arenouba/p/5469656.html
Copyright © 2011-2022 走看看