iOS之GCDAsyncSocket(TCP)

作者: CrazySteven | 来源:发表于2016-07-03 10:58 被阅读4089次

    上周周末的时候发烧了,就担误了写博客,这周就多写点吧。

    这次主要讲下Socket,关于它的三次握手、四次挥手什么的已经写的很多了,也写的很好,我就不写了。但注释代码时会穿插些Socket原理进去,当然也会提供Demo。

    TCP Socket Server

    #import "GCDAysncSocket.h"遵守协议<GCDAsyncSocketDelegate>

    创建一个socket:
    self.serverSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    监听端口:
        NSError * error = nil;
        [self.serverSocket acceptOnPort:[self.portTextField.text integerValue] error:&error];
    
    等待连接://此为GCDAsyncSocket代理方法
    - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
    {
        //这里需要对Socket的工作原理进行一点解释,当Socket accept一个连接服务请求时,将生成一个新的Socket,即此处的newSocket。在此可查看newSocket.connectedHost和newSocket.connectedPort等参数,并通过新的socket向客户端发送一包数据后会关闭你一开始创建的socket(self.serverSocket),接下来你都将使用newSocket(我将此保存为self.clientSocket)
        self.clientSocket = newSocket;
    }
    
    连接失败://此为GCDAsyncSocket代理方法
    - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err;
    {
        NSLog(@"连接失败,要怎么做,你自己看着办吧");
    }
    
    连接成功,发送数据
    //注意此处使用的是上面的newSocket
    [self.clientSocket writeData:[self.sendTextView.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
        //我创建了一个Socket单例,这里只讨论Socket,单例创建可看Demo
        SocketManager * socketManager = [SocketManager sharedSocketManager];
        [socketManager.mySocket readDataWithTimeout:-1 tag:0];
    
    对发送的数据根据tag进行管理://此为GCDAsyncSocket代理方法
    - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
    {
        NSLog(@"可通过参数中的tag值管理发送的数据,想怎么管理,您看着办");
    }
    
    连接成功,接收数据
        //同样使用的是newSocket
        [self.clientSocket readDataWithTimeout:-1 tag:0];
    
    接收数据成功,处理数据://此为GCDAsyncSocket代理方法
    - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        NSLog(@"接收到消息%@,要怎么处理,您看着办",data);
    }
    

    这是服务器Demo,欢迎大家Star


    TCP Socket Client

    #import "GCDAysncSocket.h"遵守协议<GCDAsyncSocketDelegate>

    创建Socket:
    self.clientSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    连接服务器:
        NSError * error = nil;
        [self.clientSocket connectToHost:self.ipTextField.text onPort:[self.portTextField.text integerValue] error:&error];
    
    连接成功://此处为GCDAsyncSocket代理方法
    - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
    {
        //创建的socket单例
        SocketManager * socketManager = [SocketManager sharedSocketManager];
        socketManager.mySocket = sock;
    }
    
    连接失败://此处为GCDAsyncSocket代理方法
    - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
    {
        NSLog(@"自己看着办");
    }
    
    连接成功,发送数据
        [self.clientSocket writeData:[self.sendTextView.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    
    连接成功,接收数据
        [self.clientSocket readDataWithTimeout:-1 tag:0];
    
    接收数据成功,处理数据://此处为GCDAsyncSocket代理方法
    - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        NSLog(@"接收到消息%@,要怎么处理,您看着办",data);
    }
    

    到此处就结束了,大家可以发现,客户端这边从头到尾都是使用的一个Socket,并没有出现新的Socket,这一点是需要注意的。客户端Demo,欢迎大家Star.

    版权声明:本文为 Crazy Steven 原创出品,欢迎转载,转载时请注明出处!

    相关文章

      网友评论

      • 等这姑娘老在我心里:问一下 服务端怎么进行重启 或者重新进行监听呢,现在退到后台再回到前台就不管用了
      • Hanson_HSS:你好,客户端传一个zip文件过来,知道怎么处理吗??
        CrazySteven:@Hanson_HSS 有第三方解压的
      • 玉盏:朋友你这个粘包啊
        CrazySteven:@玉盏 哦哦,你可以手动设置发送频率啊
        玉盏:@CrazySteven 我说的是粘包。。。粘包是指发送端发送的包速度过快,到接收端那边多包并成一个包的现象,比如发送端连续10次发送1个字符'a',因为发送的速度很快,接收端可能一次就收到了10个字符'aaaaaaaaaa',这就是接收端的粘包
        CrazySteven:100%自己动手敲的。
      • f0110219d1aa:请问一下,我服务端一直监听失败是什么原因?
        CrazySteven:有可能IP不在一个网段吧。。。先试试能不能ping通
      • FokHiuFai:这个demo都是只能一对一吗 我用2个客户端连的话 先连的那个就会断开
        CrazySteven:@FokHiuFai :+1:
        FokHiuFai:@CrazySteven 后面改了下可以了 要把每个新添加的socket用一个全局的数组保存下来才可以
        CrazySteven:@FokHiuFai http://www.cocoachina.com/bbs/read.php?tid-336205.html创建多个socket即可,我没连过多个,应该是可以的。
      • 小羊孩子:你好,测试可以使用一台手机一个模拟器来调试吗?手机是客户端,填写的ip 是电脑上的ip吗?端口自己随便写吗? 刚接触。大神说说吧
        CrazySteven:@小羊孩子 我测的都是正常的,一个电脑一个手机。。。
        小羊孩子:@CrazySteven 我昨天测试了, 服务端demo收不到socket。但是客户端跟我们后台服务器可以通信
        CrazySteven:@小羊孩子 可以
      • 小羊孩子:挺好。支持
      • 630c5eeb35d3:您好,想问下有没有一种情况是在连接成功的协议方法-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port中,调用了[self.asyncSocket readDataWithTimeout:-1 tag:0]; 读取数据方法成功以后,导致点击其他按钮读取数据方法不可用
        630c5eeb35d3:@CrazySteven 那可以解决吗?因为readData是要读取数据的,或者我该怎么查询错误呢?
        CrazySteven:我没有遇到过,但我认为是有可能会出现的,因为我开发中做出某些bug以后会导致一些莫名其妙的错误。这些错误并不会使你的app闪退,但会使你的app某些功能用不了。
      • 4f70f079e295:你的manager 是干什么用的
        CrazySteven:@井岗山 管理socket的
      • 4f70f079e295:为什么我这个总是显示断开链接呢?
        等这姑娘老在我心里:把对象换成Property属性看看
      • 开发者老岳:这个demo为啥还得手动接收消息,不是应该自动接收消息吗?
        开发者老岳:好使,感谢 :smile:
        CrazySteven:@老岳_ 你可以使用- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;这个方法自己去实现自动接收消息。比如你可以在连接成功后调用一次接收消息方法,然后在- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag这个方法里再调用接收消息方法,很简单的。
      • 凯文Kevin21:服务器端Demo代码有问题,客户端demo没问题。测试了一下
        凯文Kevin21:@CrazySteven 然后我换成了别人的server Demo可以收到消息。 你的demo客户端没有问题。你可以去试一下看
        凯文Kevin21:@CrazySteven 我是测试的:2台 iphone5s 都是连接的同一个wifi , 1台手机上跑客户端,1台手机上跑服务器端,开始监听端口号。 客户端向服务端通过ip+端口号发送消息, 服务端那台手机收不到消息。。。
        CrazySteven:@七秒小鱼人 有什么问题?
      • 清眸如画:自己封装的吧
        CrazySteven:@约定一生 GCDAsyncSocket不是我封装的。

      本文标题:iOS之GCDAsyncSocket(TCP)

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