zoukankan      html  css  js  c++  java
  • 【网络编程】Socket概念及简单聊天…

    Socket(套接字)
    * Socket就是为网络服务提供的一种机制
    * 通信的两端都是Socket
    * 网络通信其实就是Socket间的通信

    * 数据在两个Socket间通过IO传输

    我们来看看下面这张图:

    【网络编程】Socket概念及简单聊天实现
    如上图所示:假设客户端要向服务端发送消息,并且服务器会回应客户端。那么步骤是这样的:
    1. 必须先将带有IP+端口等数据发送给服务器,在与服务器完成三次握手后建立连接。
    2.如果建立连接成功,会出现2条传输通道,两端分别有个输出流和一个输入流。一旦连接建立成功,两端便会实时地监控各自的输入流。
    3.因为是长连接,所以连接一直存在,直至任何一方主动断开连接!

    拓展:
    关于长连接与短连接
    *一般选择长连接或者短连接由我们的需求决定,上面举的是即时通信的例子,所以选择长连接。因为如果中途一方断开,连接便失效,数据也将没有运输通道。(暂且这样理解,后面会详细讲解)
    *而平时我们常常用到得HTTP就是短连接,因为客户端只需向服务器请求一次,服务器也只需根据客户端请求的数据进行相应地回应,便不再实时交流,所以服务器在成功返回数据后便会主动断开与客户端的连接。客户端如果需要进行请求,便需要建立新的连接。

    接下来简单地实现一下聊天功能

    在DEMO里面已经放了个预先准备好的数据库,可以直接使用。使用方法:打开终端 —— 打开文件路径(cd ../../../)—— 打开文件(python chat.py)出现chat server success!字样表示启动成功。
    【网络编程】Socket概念及简单聊天实现



    然后新建项目,连接数据库,这里需要用到C语言的代码,然后再将C语言转换成OC对象

    //1.建立一个连接

       

        NSString*host = @"127.0.0.1";

        intport = 33333;

        CFReadStreamRefreadStream;     //输入流

        CFWriteStreamRefwriteStream;    //输出流

        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];

       [_outputStream open];


    实现NSStream代理方法

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

    {

        NSLog(@"%@",aStream);

        

       //   NSStreamEventOpenCompleted = 1UL << 0,   流打开成功

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

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

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

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

        switch(eventCode) {

          caseNSStreamEventOpenCompleted:

              NSLog(@"流打开成功");

               break;

          caseNSStreamEventHasBytesAvailable:

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

              [selfreadData];

               break;

          caseNSStreamEventHasSpaceAvailable:

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

               break;

          caseNSStreamEventErrorOccurred:

              NSLog(@"连接出错");

               break;

          caseNSStreamEventEndEncountered:

              NSLog(@"连接结束");

              //关闭输入输出流

              [_inputStreamclose];

              [_outputStreamclose];

              

              //从主运行循环移除

              [_inputStreamremoveFromRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];

              [_outputStreamremoveFromRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];

               break;

           default:

               break;

        }

    }


    既然是聊天,首先就需要登录,还需要一个UITextField 输入框,这边就不验证密码,直接用用户名登录

    - (void)login

    {

       // 2.聊天

       // 2.1登录

       // 发送用户名

       // 登录指令

        NSString*loginStr = @"iam:zhangsan";

        

       // Str转成NSData

       NSData*data= [loginStr dataUsingEncoding:NSUTF8StringEncoding];

        

        

        [_outputStreamwrite:data.bytesmaxLength:data.length];

    }


    登陆成功后读取服务器返回的数据

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

    -(void)readData{

        

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

        uint8_tbuf[1024];

        

       // 返回实际装的字节数

        NSIntegerlen = [_inputStreamread:bufmaxLength:sizeof(buf)];

        

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

        NSData*data = [NSDatadataWithBytes:buflength:len];

        

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

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

        

        NSLog(@"gdgdfgdf%@",recStr);

        

       [selfreloadDataWithText:recStr];

        

    }


    实现输入框代理

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

        

        NSString*text = textField.text;

        

        NSLog(@"%@",text);

       // 聊天信息

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

        

       //Str转成NSData

       NSData*data= [msgStr dataUsingEncoding:NSUTF8StringEncoding];

        

       // 刷新表格

       [selfreloadDataWithText:msgStr];

        

       // 发送数据

        [_outputStreamwrite:data.bytesmaxLength:data.length];

        

       // 发送完数据,清空textField

        textField.text= nil;

        

        return YES;

    }


    因为刷新等部分代码很多地方会用到,所以抽出来放到一个方法内方便调用

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

        [self.chatMsgsaddObject:text];

        

       [self.tableViewreloadData];

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

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

       [self.tableViewscrollToRowAtIndexPath:lastPathatScrollPosition:UITableViewScrollPositionBottomanimated:YES];

    }


    最后就是完成Tableview的数据集

    #pragma mark 表格的数据源


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

        return self.chatMsgs.count;

    }



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

    {

        staticNSString*ID = @"Cell";

       UITableViewCell*cell= [tableView dequeueReusableCellWithIdentifier:ID];

        

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

        

        return cell;

    }


    运行效果如下:
    【网络编程】Socket概念及简单聊天实现



    Socket的概念和简单使用就先到这里了,需要DEMO的可以到下面链接下载:
    链接: http://pan.baidu.com/s/1mgITR7M 密码: q916

    如果有错误或者有什么问题可以联系我,转载请注明出处,谢谢!



  • 相关阅读:
    UVa10779
    UVa10779
    C++ 内存管理学习笔记
    c++ 学习笔记
    AcWing 275 传纸条
    I
    Tree HDU6228
    Lpl and Energy-saving Lamps
    C
    Secret Poems
  • 原文地址:https://www.cnblogs.com/miaomiaoshen/p/5188638.html
Copyright © 2011-2022 走看看