OC原生的输入输出流结合socket实现即时通讯

来源:互联网 发布:域名未授权 编辑:程序博客网 时间:2024/06/10 07:00

#import "ViewController.h"


@interface ViewController ()<NSStreamDelegate,UITextFieldDelegate,UITableViewDataSource,UITableViewDelegate>{

    NSInputStream *_inputStream;//对应输入流

    NSOutputStream *_outputStream;//对应输出流

}

@property (weak, nonatomic) IBOutletNSLayoutConstraint *inputViewConstraint;

@property (weak, nonatomic) IBOutletUITableView *tableView;


@property (nonatomic,strong) NSMutableArray *chatMsgs;//聊天消息数组


@end


@implementation ViewController


-(NSMutableArray *)chatMsgs{

    if (!_chatMsgs) {

        _chatMsgs = [NSMutableArrayarray];

    }

    

    return_chatMsgs;

}


- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

  

    

    // 2.收发数据

    // 做一个聊天

    // 1.用户登录

    // 2.收发数据

    

    // 监听键盘

    [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(kbFrmWillChange:)name:UIKeyboardWillChangeFrameNotificationobject:nil];

}



-(void)kbFrmWillChange:(NSNotification *)noti{

    NSLog(@"%@",noti.userInfo);

    

    // 获取窗口的高度

    

    CGFloat windowH = [UIScreenmainScreen].bounds.size.height;

    

   

    

    // 键盘结束的Frm

    CGRect kbEndFrm = [noti.userInfo[UIKeyboardFrameEndUserInfoKey]CGRectValue];

     // 获取键盘结束的y

    CGFloat kbEndY = kbEndFrm.origin.y;

    

    

    self.inputViewConstraint.constant = windowH - kbEndY;

}

//流的代理方法,这个代理方法是在主线程运行的

-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{

    NSLog(@"%@",[NSThreadcurrentThread]);


//    NSStreamEventOpenCompleted = 1UL << 0,//输入输出流打开完成

//    NSStreamEventHasBytesAvailable = 1UL << 1,//有字节可读

//    NSStreamEventHasSpaceAvailable = 1UL << 2,//可以发放字节

//    NSStreamEventErrorOccurred = 1UL << 3,// 连接出现错误

//    NSStreamEventEndEncountered = 1UL << 4// 连接结束

    switch (eventCode) {

        caseNSStreamEventOpenCompleted:

            NSLog(@"输入输出流打开完成");

            break;

        caseNSStreamEventHasBytesAvailable:

            NSLog(@"有字节可读");

            [self readData];

            break;

        caseNSStreamEventHasSpaceAvailable:

            NSLog(@"可以发送字节");

            break;

        caseNSStreamEventErrorOccurred:

                        NSLog(@"连接出现错误");

            break;

        caseNSStreamEventEndEncountered:

             NSLog(@"连接结束");

            

            // 关闭输入输出流

            [_inputStream close];

            [_outputStream close];

            

            // 从主运行循环移除

            [_inputStreamremoveFromRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];

            [_outputStreamremoveFromRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];

            break;

        default:

            break;

    }

    

}


- (IBAction)connectToHost:(id)sender {

    // 1.建立连接

    NSString *host = @"127.0.0.1";

    int port = 12345;

    

    // 定义C语言输入输出流

    CFReadStreamRef readStream;

    CFWriteStreamRef writeStream;

//    参数一:分配内存空间

//    参数二:主机

//    参数三:端口号

//    参数四:输入流

//    参数五:输出流

    CFStreamCreatePairWithSocketToHost(NULL, (__bridgeCFStringRef)host, port, &readStream, &writeStream);

    

    // C语言的输入输出流转化成OC对象

    _inputStream = (__bridgeNSInputStream *)(readStream);

    _outputStream = (__bridgeNSOutputStream *)(writeStream);

    

    

    // 设置代理

    _inputStream.delegate =self;

    _outputStream.delegate =self;

    

    

    // 把输入输入流添加到主运行循环

    // 不添加主运行循环代理有可能不工作

    [_inputStreamscheduleInRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];

    [_outputStreamscheduleInRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];

    

    // 打开输入输出流

    [_inputStream open];

    [_outputStreamopen];

}



- (IBAction)loginBtnClick:(id)sender {

    

    // 登录

    // 发送用户名和密码

    // 在这里做的时候,只发用户名,密码就不用发送

    

    // 如果要登录,发送的数据格式为 "iam:zhangsan";

    // 如果要发送聊天消息,数据格式为 "msg:did you have dinner";

    

    //登录的指令

    NSString *loginStr = @"iam:zhangsan";

    

    //Str转成NSData(网络传输都是二进制)

    NSData *data = [loginStrdataUsingEncoding:NSUTF8StringEncoding];


    //写数据,是输出流

    [_outputStream write:data.bytes maxLength:data.length];

}


#pragma mark 读了服务器返回的数据

-(void)readData{

    

    //建立一个缓冲区可以放1024个字节

    uint8_t buf[1024];

    

    // 返回实际装的字节数

    NSInteger len = [_inputStreamread:buf maxLength:sizeof(buf)];


    // 把字节数组转化成字符串

    NSData *data = [NSDatadataWithBytes:buf length:len];

    

    // 从服务器接收到的数据

    NSString *recStr =  [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];

    

    NSLog(@"%@",recStr);

    

    [selfreloadDataWithText:recStr];

    

}


-(BOOL)textFieldShouldReturn:(UITextField *)textField{

    

    NSString *text = textField.text;

    

    NSLog(@"%@",text);

    // 聊天信息

    NSString *msgStr = [NSStringstringWithFormat:@"msg:%@",text];

    

    //Str转成NSData

    NSData *data = [msgStrdataUsingEncoding:NSUTF8StringEncoding];

    

    // 刷新表格

    [selfreloadDataWithText:msgStr];

    

    // 发送数据

    [_outputStream write:data.bytes maxLength:data.length];

    

    // 发送完数据,清空textField

    textField.text = nil;

    

    return YES;

}


-(void)reloadDataWithText:(NSString *)text{

    [self.chatMsgsaddObject:text];

    

    [self.tableViewreloadData];

    

    // 数据多,应该往上滚动

    NSIndexPath *lastPath = [NSIndexPathindexPathForRow:self.chatMsgs.count -1 inSection:0];

    [self.tableViewscrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottomanimated:YES];

}


#pragma mark 表格的数据源


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.chatMsgs.count;

}



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *ID =@"Cell";

    UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID];

   

    cell.textLabel.text =self.chatMsgs[indexPath.row];

    

    return cell;

}


-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{

    [self.viewendEditing:YES];

}

@end


0 0
原创粉丝点击