Socket学习

之前一直没做过socket相关的项目,在智能家居领域socket应用还是比较广泛的,所以一直想着学习socket相关知识,正好最近项目不是很忙,就想着补一补之前要学但是没学的东西。

  1. iOS里的socket主要是基于CFSocket来做的,原生socket是用c语言写的,调用的方式有点复杂,所以一般很少会用到,可以看这个链接了解一下即可

  2. 这里主要说一下对原生CFSocket进行封装过的第三方库GCDAsyncSocket,这个库应用还是比较广泛的,github上的star数量达到了11.8k。(在github上要搜索CocoaAsyncSocket才能搜到,直接搜GCDAsyncSocket的话搜到的都是各种demo)

  3. GCDAsyncSocket的简单使用,直接把GCDAsyncSocket.hGCDAsyncSocket.m复制进项目即可使用

  4. Server代码:

    //初始化
    self.connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
    self.serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    //开始监听端口
    [self.serverSocket acceptOnPort:port error:&error];
    
      #pragma mark - GCDAsyncSocketDelegate
      //有客户端连接时会调用
      - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
          NSLog(@"%s", __func__);
          //保持对newSocket的引用,使用newSocket来发送和读取数据,newSocket和sock有相同的代理
          //下面几个代理方法中的sock即为此处的newSocket
          [self.connectedSockets addObject:newSocket];
          NSData *data = [@"欢迎连接!" dataUsingEncoding:NSUTF8StringEncoding];
          [newSocket writeData:data withTimeout:-1 tag:0];
      }
      //写入数据完成回调
      - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
          NSLog(@"%s", __func__);
          [sock readDataWithTimeout:-1 tag:tag];
      }
      //读取数据完成回调
      - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
          NSLog(@"%s", __func__);
          NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
          NSLog(@"string: %@", message);
          NSString *sendString = [@"你说:" stringByAppendingString:message];
          NSData *sendData = [sendString dataUsingEncoding:NSUTF8StringEncoding];
          [sock writeData:sendData withTimeout:-1 tag:tag];
      }
    
     在调试过程中遇到的问题:   
     1. 没有设置`delegatequeue`报错,初始化时设置为`dispatch_get_main_queue`即可
     2. 客户端发来的数据没有读取到,需要显示的调用`readDataWithTimeout`方法来读取数据
    
  5. Client代码:

    //初始化
    self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    //开始连接
    NSError *error;
    [self.clientSocket connectToHost:hostIP onPort:hostPort.integerValue error:&error];
    
      #pragma mark - GCDAsyncSocketDelegate
      //成功连接到服务器
      - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
          NSLog(@"%s", __func__);
          NSData *data = [@"已经连接!" dataUsingEncoding:NSUTF8StringEncoding];
      		[sock writeData:data withTimeout:-1 tag:0];
      }
      //写入数据完成
      - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
          NSLog(@"%s", __func__);
          [sock readDataWithTimeout:-1 tag:tag];
      }
      //读取数据完成
      - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
          NSLog(@"%s", __func__);
          NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
          NSLog(@"string: %@", string);
          [sock readDataWithTimeout:-1 tag:0];
      }
    
     在调试过程中遇到的问题:
     1. 收到的数据不是最新的,而是上一次发的数据,需要在`didReadData`方法的最后,再调用`readDataWithTimeout`即可
    
  6. 用到的调试工具
    刚开始连接运行两个demo,分别在手机和电脑上测试,一直连不上,不知道什么问题,百度之后发现了sockit这个调试工具。使用homebrew安装,就可以在mac上调试socket,可以分别模拟客户端和服务端进行调试,非常方便。

posted @ 2020-11-17 21:43  yuyuyu37  阅读(116)  评论(0编辑  收藏  举报