iOS 即时通讯,简单socket网络编程一<socket 底层>

来源:互联网 发布:淘宝能开刻章店吗 编辑:程序博客网 时间:2024/06/17 01:54

本篇文章简单介绍一下iOS的socket即时通讯底层的实现。

<1>socket简单的本地服务器的搭建,大家可以参考博客http://www.jianshu.com/p/39a68332e19f   。

<2>iOS  socket编程的底层是通过调用C语言的函数,并通过OC和C语言的桥接,通过输入输出流进行数据读写,进行及时通讯。下面是一个简单的socket网络编程的demo。
////  ViewController.m//  SocketTest////  Created by fe on 16/9/4.//  Copyright © 2016年 fe. All rights reserved.//#import "ViewController.h"@interface ViewController ()<NSStreamDelegate,UITextFieldDelegate,UITableViewDelegate,UITableViewDataSource>@property(nonatomic,strong) NSInputStream *inputStream;@property(nonatomic,strong) NSOutputStream *outputStream;//拿到输入框文本,以便修改位置@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textFieldCounterbottom;//用于存放聊天内容的数组@property (nonatomic,strong) NSMutableArray *msgArry;@property (weak, nonatomic) IBOutlet UITableView *msgTableView;@end@implementation ViewController- (NSMutableArray *)msgArry{    if (!_msgArry) {        _msgArry = [[NSMutableArray alloc] init];    }    return _msgArry;}- (void)viewDidLoad {    [super viewDidLoad];    //监听键盘    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(theKeyBoardDidChanged:) name:UIKeyboardWillChangeFrameNotification object:nil];    }#pragma mark - NSStreamDelegate-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{//    NSStreamEventOpenCompleted = 1UL << 0,//输入输出流打开完成//    NSStreamEventHasBytesAvailable = 1UL << 1,//有字节可读//    NSStreamEventHasSpaceAvailable = 1UL << 2,//可以发送字节//    NSStreamEventErrorOccurred = 1UL << 3,//链接出现了错误//    NSStreamEventEndEncountered = 1UL << 4//结束    switch (eventCode) {        case NSStreamEventOpenCompleted:            NSLog(@"输入输出流打开完成");            break;        case NSStreamEventHasBytesAvailable:            NSLog(@"有字节可读");            [self readData];            break;        case NSStreamEventHasSpaceAvailable:            NSLog(@"可以发送字节");                        break;        case NSStreamEventErrorOccurred:            NSLog(@"链接出现了错误");                        break;        case NSStreamEventEndEncountered:            NSLog(@"结束");            //关闭输入输出流            [self.inputStream close];            [self.outputStream close];            //从主循环移除            [self.inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];            [self.outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];            break;                    default:            break;    }}- (IBAction)connectToInternet:(id)sender {    //1:建立连接    NSString *localHost = @"127.0.0.1";//本机地址    int port = 12345;//服务器端口    //定义c语言输入输出流    CFReadStreamRef readStream;    CFWriteStreamRef writeStream;    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(localHost), port, &readStream, &writeStream);    //把c语言的输入输出流转化为oc对象    self.inputStream = (__bridge NSInputStream *)readStream;    self.outputStream = (__bridge NSOutputStream *)(writeStream);        //设置输入输出流的代理    self.inputStream.delegate = self;    self.outputStream.delegate = self;    //把输入输出流添加到主运行循环    [self.inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];    [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];    //打开输入输出流    [self.inputStream open];    [self.outputStream open];}- (IBAction)login:(id)sender {        //2:收发数据    //2.1:登陆  发送用户名和密码 这里我们只简单的发送一个用户名进行登陆    //如果登陆发送的数据格式为 “iam:zhengyanfneg”    //如果发送消息发送的数据格式为 “msg:How are you”    //登陆指令    NSString *loginStr = @"iam:zhengyanfeng";    //将字符串转化为data    NSData *loginData = [loginStr dataUsingEncoding:NSUTF8StringEncoding];        [self.outputStream write:loginData.bytes maxLength:loginData.length];            }#pragma mark - 读取服务器返回的数据- (void)readData{    //建立数据缓冲区可以放1024个字节(字节数组)    uint8_t buf[1024];    //length 返回的实际字节长度    NSInteger length =[self.inputStream read:buf maxLength:sizeof(buf)];    //把字节转化成字符串    NSData *receiveData =[NSData dataWithBytes:buf length:length];    NSString *receiveStr = [[NSString alloc] initWithData:receiveData encoding:NSUTF8StringEncoding];    [self reloadDataWithString:receiveStr];    }#pragma mark - UITextFieldDelegate- (BOOL)textFieldShouldReturn:(UITextField *)textField{    //发送聊天数据    NSString *mesStr = [NSString stringWithFormat:@"msg:%@",textField.text];    [self reloadDataWithString:mesStr];    NSData *strData = [mesStr dataUsingEncoding:NSUTF8StringEncoding];    [self.outputStream write:strData.bytes maxLength:strData.length];    textField.text = nil;    return YES;}//监听键盘位置变化的方法- (void)theKeyBoardDidChanged:(NSNotification *)noti{    NSLog(@"%@",noti.userInfo);    CGFloat windowH = [UIScreen mainScreen].bounds.size.height;    CGRect keyboardFrame = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];    CGFloat keyboardY = keyboardFrame.origin.y;    self.textFieldCounterbottom.constant = windowH - keyboardY;}#pragma mark - UITableViewDelegate UITableViewDataSource-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return self.msgArry.count;}-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    NSString *const reuseID = @"socketCell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseID];    cell.textLabel.text = self.msgArry[indexPath.row];    return cell;}- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{    [self.view endEditing:YES];}//向聊天数组添加数据并刷新表格- (void)reloadDataWithString:(NSString *)msgStr{    [self.msgArry addObject:msgStr];    [self.msgTableView reloadData];    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(self.msgArry.count -1 ) inSection:0];    [self.msgTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];}@end


0 0