美文网首页
基于XMPP实现(简单搭建一)

基于XMPP实现(简单搭建一)

作者: Leo乀垚 | 来源:发表于2017-08-22 20:31 被阅读0次

    准备工作:开启ChatSever服务 ——— python 文件名(终端输入: cd phthon文件路径)

    first Step:

    1、简单聊天室(socket):

    *实现登陆功能:

    http://192.168.1.1/login实现登陆的功能 ①username ②password 传递给服务器

    socket:192.168.1.1:123456(端口号)

    登陆指令:iam:zhangsan

    2、实现发送聊天信息的功能

    发送聊天数据指令:msg:******

    second Step:

    ①连接实现:

    iOS里实现socket的连接,使用C语言

    1.与服务器通过三次握手建立连接:

    - (void)connectToServer:(id)sender {

    NSString *host = @"127.0.0.1";

    int port = 12345;

    //全局队列

    //创建一个socket对象

    GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIOROTY_DEFAULT, 0)];

    //主队列

    GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    //连接

    NSError *error = nil;

    [socket connectToHost:host onPort:port error:&error];

    if (error) {

    NSLog(@"%@", error);

    }

    }

    2.定义输入输出流

    CFReadStreamRef readStream;

    CFWriteStreamRef writeStream;

    3.分配输入输出流的内存空间

    CFStreamCreatePairWithSocketToHost(NULL, (_bridge CFStringRef)host, port(端口号), &readStream, &writeStream);

    4.把C语言的输入输出流转成OC对象

    在外面写大括号里的

    {

    NSInputStream *_inputStream;

    NSOutputStream *_outStream;

    }

    _inputStream = (_bridge NSInputStream *)readStream;

    _outStream = (_bridge NSOutStream *)writeStream;

    5.设置代理, 监听数据接收的状态(NSStreamDelegate):

    _outputStream.delegate = self;

    _inputStream.delegate = self;

    把输入输出流添加到主运行循环(主运行循环是监听网络状态的)

    [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefauleRunLoopMode];

    [_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefauleRunLoopMode];

    6.打开输入输出流

    [_inputStream open];

    [_outputStream open];

    7.实现代理协议

    - (void)Stream:(NSStream *)aStream handeleEvent:(NSStreamEvent)eventCode{

    swith (eventCode) {

    case NSStreamEventOpenCompleted:

    NSLog(@"成功连接建立,形成输入输出流的传输通道”);

    break;

    case NSStreamEventHasBytesAvailable:

    NSLog(@"有数据可读”);

    [self readData];

    break;

    case NSStreamEventHasSpaceAvailable:

    NSLog(@"可以发送数据"):

    break;

    case NSStreamEventErrorOccurred:

    NSLog(@"有错误发生,连接失败");

    break;

    case NSStreamEventEndEncountered:

    NSLog(@"正常的断开连接");

    //把输入输出流关闭, 并且从主运行循环中移除

    [_inputStream close];

    [_outputStream close];

    [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    [_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    break;

    default:

    breeak;

    }

    }

    登陆

    - (void)loginClick:(id)sender {

    发送登陆请求,输出流(给数据的)

    //接登陆的指令 iam:zhangsan

    NSString *loginStr = @"iam:zhangsan";

    //self sendDataToHost:loginStr];

    //②:使用AsyncSocket

    //-1代表 不设置超时

    [_socket writeData:[loginStr dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:101];

    }

    读取服务器返回的数据

    - (void)readData {

    //定义缓冲区 (只能存储1024字节)

    uint8_t buf[1024];

    //读取数据

    //len为服务器读取到的实际字节数

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

    //把缓冲区的实际字节数转成字符串

    NSString *receiveStr = [[NSString alloc] initWithBytes:buf lenght:len encoding:NSUTF8StringEncoding];

    NSLog(@"%@", receiveStr);

    //把数据源添加进数组中

    [self.msgs addObject:receiveStr];

    [self.tableView reloadData];

    }

    Third Step:

    首先绘制聊天界面(把底部输入栏的约束拖过来:bottomContraint), 之后在control中编写键盘监听:

    [[NSNotificationCenter defaultCenter] addObserver: self selecter:@selector(kbWillShow:) name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver: self selecter:@selector(kbWillHide:) name:UIKeyboardWillHideNotification object:nil];

    ②:实现监听方法

    键盘将要显示:

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

    //显示的时候将要改变bottomContraint

    //获取键盘高度

    CGFloat kbHeight = [noti.userInfo[UIKeyboardFrameEndUserInfoKey]CGRectVaule].size.height;

    self.botttomConstraint.constant = kbHeight;

    }

    //设置信息显示的tableView的代理, 控制键盘的消失

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

    reurn self.msgs.count;

    }

    - (UITableViewCell *)tableView:(UITabelView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:@"ChatCell"];

    //显示信息

    cell.textLable.text = self.msgs[indexPath.row];

    }

    //将要开始拖动的时候,如果键盘显示就回收

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

    //隐藏键盘

    [self.view endEditing:YES];

    }

    键盘将要消失:

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

    }

    //把监听移除

    - (void)dealloc {

    [NSNotifiactionCenter dafaultCenter] removeObserver:self];

    }

    //实现信息的发送(UITextFieldDelegate):

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

    //发送信息

    //1.有数据发送

    NSString *txt = textField.text;

    if (txt.length == 0) {

    return YES;

    }

    NSString *msg = [@"msg:" stringByAppendingString:txt];

    [self sendDataToHost:msg];

    return YES;

    }

    //发送数据

    - (void)sendDataToHost:(NSString *)str {

    //uint8_t * 代表字符数组

    // NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

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

    //②:

    [_socket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:102];

    }

    fourth Step:实现聊天信息的展示

    ①:定义一个数组(msgs),存储信息

    实现asyncSocket(添加文件GCDAsyncSocket): 在建立连接的时候添加异步

    遵循socketDelegate协议,

    ①:连接成功的代理方法

    - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{

    NSLog(@"%s", __func__);

    }

    ②:断开连接的代理方法

    - (void)socketDidDiscommect:(GCDAsyncSocket *)sock withError:(NSError *

    err {

    if(err) {

    NSLog(@"连接失败“);

    }else {

    NSLog(@"正常断开”);

    }

    }

    ④:数据发送成功

    - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {

    //发送完数据手动读取

    [sock readDataWithTimeout:-1 tag:tag];

    }

    ③:读取数据 (在子线程调用的, 因为是全局队列,刷新有延迟; 如果是在主队列中,就会立即显示)

    - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {

    NSString *receiveStr = [[NSString alloc] initWithData:data         encoding:NSUTF8StringEncoding];

    if (tag == 101) {//登陆tag

    }  else if (tag == 102) {//聊天数据

    [sefl.msgs addObject:receiverStr];

    //刷新表格

    [self.tabelView reloadData];

    }

    }

    相关文章

      网友评论

          本文标题:基于XMPP实现(简单搭建一)

          本文链接:https://www.haomeiwen.com/subject/hjfrdxtx.html