• GCDAynscSocket简单使用-客户端


    这是一篇介绍GCDAynscSocket客户端简单使用的文章(服务端后续添加)

    背景:在这篇文章之前我对socket的了解仅限于知道有TCP、UDP两种方式,使用抓包工具时甚至看不懂抓包数据(惭愧...),所以本文介绍内容深度有限,主要介绍了一些简单用法。

    在这篇文章中主要介绍:

    1、使用GCDAynscSocket创建连接、发送数据、接收数据、断开连接;

    2、发生数据粘包的处理。

    ------------------------------------------------------------------------------------

    1、创建连接

    GCDAynscSocket的初始化般使用两种方式:

      // aDelegate是设置的委托对象,而dq是委托所在的线程,sq是socket所在的线程。其中dp不能为空,sq可以为空

      - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;

      - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;

      /**
      * @brief 连接到服务器
      */
      - (void)socketConnectHost
      {

        self.socket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:delegateQueue];

        NSError *error = nil;

        [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error];

        [self.socket readDataWithTimeout:30 tag:100];

      }

    连接是否成功都是在委托方法中查看的

    // 连接成功的委托方法  

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

    {

      NSLog(@"连接成功了...");

    }

    // 连接失败或中途断开连接的委托方法

    - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err

    {

      NSLog(@"连接失败... 断开连接了...");  

    }

    2、发送数据

      发送数据比较简单,调用[self.socket writeData:data withTimeout:-1 tag:1]即可

      /**

       *  @brief   写入字符串数据

       *  @param   sendStr 要写入的字符串

       */

      - (void)writeAndSendData:(NSString *)sendStr

      {

          NSData *data = [sendStr dataUsingEncoding: NSUTF8StringEncoding];

          [self.socket writeData:data withTimeout:-1 tag:1];

      }

    3、接收数据

      // 在委托方法中接收数据

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

      {

          // 对得到的data值进行解析

          [self parseSocket:sock withData:data withTag:tag];

      }

    在此处有一个疑问:

    在接收数据之前,是否必须执行[self.socket readDataWithTimeout:-1 tag:100]??最初开始使用时,是必须添加的否则接收不到数据,但是现在工程中没有执行这句代码,为什么可以一直接收数据呢?

    4、断开连接

      断开连接直接调用方法[self.socket disconnect]即可,可以在委托方法查看是否断开

      /**

       *  @brief   切断socket

       */

      -(void)cutOffSocket

      {

          [self.socket disconnect];

      }

    5、数据粘包处理

    通常在tcp中都要处理数据粘包。我使用的是给数据添加包头的方式,这也是网上比较推荐的一种方式。

    思路:定义好包头协议后,在数据发送端每次发送数据之前都添加一个包头(因为是每次发送都添加,所以我认为只要能够满足解包需求包头要尽可能短)。接收端根据包头信息对接收到的数据进行拆包。

    一个简单的包头数据:  有5个字节包含两项内容开始:字符$和数据包长度msgLen。

        char     startStr = '$';

        uint32_t msgLen;

        msgLen  = (uint32_t)(str.length + 5); 

    在接收端接收到数据后,根据包头信息,找到开始字符$,然后读出包的长度,即可正确拆包。

    在整个过程中要注意:如果发送端对数据进行了编码,那么接收端要进行相应的解码,否则会造成乱码,拆包失败。

    总结:

    在整个使用学习过程中,网络知识一窍不通,又无人指导,感觉举步维艰,还好最终实现了!回头看看前面自己绕的弯路觉得很可笑,纠结的问题更是...

    且学且努力!

  • 相关阅读:
    Binary Trees
    [POJ] String Matching
    Tree
    Maxmum subsequence sum problem
    poj 2104 划分树
    poj 2486 树形dp
    poj 1848 树形dp
    hdu 4578 线段树
    hdu 4585 set应用
    hdu 2412 树形DP
  • 原文地址:https://www.cnblogs.com/songshu-yilia/p/4549160.html
Copyright © 2020-2023  润新知