IOS Socket 04-利用框架CocoaAsyncSocket实现客户端/服务器端

这篇文章,我们介绍CocoaAsyncSocket框架的使用,主要介绍实现客户端/服务器端代码,相信在网上已经很多这样的文章了,这里做一下自己的总结。这里介绍使用GCD方式

一.客户端

1.下载地址

读者可以在github下载框架源码 https://github.com/robbiehanson/CocoaAsyncSocket

下载后,可以看到在Examples下面可以看到很多例子,如果读者自学能力高,可以略过下面的文章。

2.开始使用

1)在 \Source\GCD 目录下,我们可以看到GCDAsyncSocket的h与m文件,我们复制这两个文件到项目中。

2)我们在代码里面导入头文件 #import "GCDAsyncSocket.h" 与 协议 GCDAsyncSocketDelegate。

3.代码

1)定义全局变量 GCDAsyncSocket *_socket;

2)开始连接服务器

- (void) connect2Server() {
    //1.主机与端口号
    NSString *host = @"127.0.0.1";
    int port = 12345;

    //初始化socket,这里有两种方式。分别为是主/子线程中运行socket。根据项目不同而定
    _socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];//这种是在主线程中运行
    //_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; 这种是在子线程中运行

    //开始连接
    NSError *error = nil;
    [_socket connectToHost:host onPort port error:&error];
    if(error) {
        NSLog("error:%@", error);
    }

}

3)登录

-(void)login() {
    //登录String
    NSString *loginStr = "iam:I am login!";
    NSData *loginData = [loginStr dataUsingEncoding: NSUTF8StringEncoding];
    //发送登录指令。-1表示不超时。tag200表示这个指令的标识,很大用处
    [_socket writeData: loginData withTimeout:-1 tag:200];
}

4)开始聊天

//发送聊天数据
-(void) sendMsg: (NSString*)msg{
    NSString *sendMsg = [@"msg:I send message to u!"];
    NSData *sendData = [sendMsg dataUsingEncoding: NSUTF8StringEncoding];
    [_socket writeData; sendData withTimeout:-1 tag:201];
}

5)实现协议delegate

#pragma mark -socket的代理

#pragma mark 连接成功

-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    //连接成功
    NSLog(@"%s",__func__);
}

#pragma mark 断开连接
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    if (err) {
        NSLog(@"连接失败");
    }else{
        NSLog(@"正常断开");
    }
}

#pragma mark 数据发送成功
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"%s",__func__);
    //发送完数据手动读取
    [sock readDataWithTimeout:-1 tag:tag];
}

#pragma mark 读取数据
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    //代理是在主/子线程调用
    NSLog(@"%@",[NSThread currentThread]);
    NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    if (tag == 200) {
    //登录指令
     }else if(tag == 201){
    //聊天数据
    }
    NSLog(@"%s %@",__func__,receiverStr);}

二.服务器端

服务器端不可能在iphone/ipad上运行,所以我们新建一个单纯命令行的项目。

1.新建一个类MyChatServer,并且开放公共方法startServer,头文件如下

#import <Foundation/Foundation.h>

@interface MyChatServer : NSObject
/**
 *  开启聊天服务器
 */
-(void)startServer;
@end

2.在main文件中,开启聊天服务器,并且开启主运行循环,让服务器接收到客户端请求

//实现聊天
MyChatServer *chatServer = [[MyChatServer alloc] init];
[chatServer startServer];
//开启主运行循环
[[NSRunLoop currentRunLoop] run];

3.在MychatServer.m文件中,我们开始实现GCDAsyncSocket的方法(下面代码都在MychatServer.m中)

1)首先建一个成员变量array对象,把所有的socket(客户端)对象保存在里面

@property(strong,nonatomic)NSMutableArray *clientSocket;

私有变量serverSocket与golbal_queue

GCDAsyncSocket *_serverSocket;
dispatch_queue_t _golbalQueue;

2)在类初始化的时候,我们初始化私有变量与成员变量

-(instancetype)init{
    if (self = [super init]) {
      _clientSocket = [NSMutableArray array];
      //创建全局queue
      _golbalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      //创建服务端的socket,注意这里的是初始化的同时已经指定了delegate
      _serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:_golbalQueue];
    }
    return self;
}

3)开启服务器聊天startServer

-(void)startChatServer{
    //打开监听端口
    NSError *err;
    [_serverSocket acceptOnPort:12345 error:&err];
     if (!err) {
        NSLog(@"服务开启成功");
    }else{
        NSLog(@"服务开启失败");
    }
}

4)实现delegate

#pragma mark 有客户端建立连接的时候调用
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
    //sock为服务端的socket,服务端的socket只负责客户端的连接,不负责数据的读取。   newSocket为客户端的socket
    NSLog(@"服务端的socket %p 客户端的socket %p",sock,newSocket);
    //保存客户端的socket,如果不保存,服务器会自动断开与客户端的连接(客户端那边会报断开连接的log)
    NSLog(@"%s",__func__);
    [self.clientSocket addObject:newSocket];

    //newSocket为客户端的Socket。这里读取数据
    [newSocket readDataWithTimeout:-1 tag:100];
}

#pragma mark 服务器写数据给客户端
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"%s",__func__);
    [sock readDataWithTimeout:-1 tag:100];
}

#pragma mark 接收客户端传递过来的数据
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    //sock为客户端的socket
    NSLog(@"客户端的socket %p",sock);
    //接收到数据
    NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"length:%ld",receiverStr.length);
    // 把回车和换行字符去掉,接收到的字符串有时候包括这2个,导致判断quit指令的时候判断不相等
    receiverStr = [receiverStr stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    receiverStr = [receiverStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];

    //判断是登录指令还是发送聊天数据的指令。这些指令都是自定义的
    //登录指令
    if([receiverStr hasPrefix:@"iam:"]){
        // 获取用户名
        NSString *user = [receiverStr componentsSeparatedByString:@":"][1];
        // 响应给客户端的数据
        NSString *respStr = [user stringByAppendingString:@"has joined"];
      [sock writeData:[respStr dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    }
    //聊天指令
    if ([receiverStr hasPrefix:@"msg:"]) {
        //截取聊天消息
        NSString *msg = [receiverStr componentsSeparatedByString:@":"][1];
      [sock writeData:[msg dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    }
    //quit指令
    if ([receiverStr isEqualToString:@"quit"]) {
        //断开连接
        [sock disconnect];
        //移除socket
       [self.clientSocket removeObject:sock];
    }
    NSLog(@"%s",__func__);
}

查看本文章之前,可以看看

IOS Socket 03-建立连接与登录

时间: 2024-08-25 15:00:02

IOS Socket 04-利用框架CocoaAsyncSocket实现客户端/服务器端的相关文章

iOS:基于Socket的第三方框架CocoaAsyncSocket的使用

CocoaAsyncSocket无疑是目前封装得最完善的Socket库了:支持异步TCP/UDP,支持GCD,Objective-C接口封装,同时还有日志跟踪功能,使用此日志跟踪,程序员可以很方便的进行调试. 文件如下:   如果想打开日志调试,很简单,导入需要的DDASLLogger.h头文件,创建DDASLLogger单利对象就可以了. 简单的演示如下: 1.在故事版布局 2.在ViewController.h文件中 // ViewController.h // AysnSocket #im

iOS Socket 整理以及CocoaAsyncSocket、SRWebSocket源码解析(一)

写在准备动手的时候: Socket通讯在iOS中也是很常见,自己最近也一直在学习Telegram这个开源项目,Telegram就是在Socket的基础上做的即时通讯,这个相信了解这个开源项目的也都知道,希望自己能慢慢的了解一下它的这个MtProtoKit开源协议,即时通讯这一块的东西我以前写过一篇<iOS 即时通讯 + 仿微信聊天框架 + 源码>,从点击量看的出来真的这一块的东西我们的需求量还是很大,<iOS 即时通讯 + 仿微信聊天框架 + 源码>这篇文章由于自己去年也是能力有限

iOS socket Stream 服务器端 及 客户端 演示

iOS socket Stream 测试环境,mac osx 10.8 一:建立服务器端 由于mac osx10.8 已经集成 python2和 Twisted,我们可以直接利用此,构建一个简单的socket 服务器 如下测试一个简单的聊天 socket 并,定义,加入聊天时发送:iam:用户名 发送信息时:msg:信息 终端:vim server.py  回车,copy入如下代码 from twisted.internet.protocol import Factory, Protocol f

Socket编程(简易聊天室客户端/服务器编写、CocoaAsyncSocket)

Socket编程(简易聊天室客户端/服务器编写.CocoaAsyncSocket) 一.Socket 1.1 Socket简介 Socket就是为网络服务提供的一种机制.网络通信其实就是Socket间的通信,通信的两端都是Socket,数据在两个Socket间通过IO传输. 在Web服务大行其道的今天,调用Web服务的代价是高昂的,尤其是仅仅是抓取少量数据的时候尤其如此.而使用Socket,可以只传送数据本身而不用进行XML封装,大大降低数据传输的开销.Socket允许使用长连接,允许应用程序运

iOS Socket理论知识

iOS Socket理论知识 序言 网络七层由下往上分别为物理层.数据链路层.网路层.传输层.会话层.表示层和应用层.其中物理层.数据链路层和网络层通常被称作媒体称,是网络工程师所研究的对象;传输层.会话层.表示层和应用层则被称作主机层,是用户所面向和关心的内容. http协议对应与应用层 TCP/UDP协议对应于传输层 IP协议对应于网络层 三者本质上没有可比性.何况HTTP协议是基于TCP连接的.TCP/IP是传输层协议,主要解决数据如何在网络中传输:而HTTP是应用层协议,主要解决如何包装

IOS socket编程--Asyncsocket

iPhone的标准推荐是CFNetwork 库编程,其封装好的开源库是 cocoa AsyncSocket库,用它来简化CFNetwork的调用,它提供了异步操作 主要特性有: 队列的非阻塞的读和写,而且可选超时.你可以调用它读取和写入,它会当完成后告知你 自动的socket接收.如果你调用它接收连接,它将为每个连接启动新的实例,当然,也可以立即关闭这些连接 委托(delegate)支持.错误.连接.接收.完整的读取.完整的写入.进度以及断开连接,都可以通过委托模式调用 基于run loop的,

iOS Socket介绍及其简单应用

socket,究竟是什么东东,面试时,笔试有他,面试也有他,如果做智能硬件,肯定会用到socket,所以,今天带大家回顾一下socket: 一.介绍:Socket:是应?层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是 一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接?后面:例: 你要打电话给?个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了.等交流结束,挂断电话结束此次交谈. 建立连接步骤:先从服

iOS超全开源框架、项目和学习资料汇总(5)AppleWatch、经典博客、三方开源总结篇

完整项目 v2ex – v2ex 的客户端,新闻.论坛.apps-ios-wikipedia – apps-ios-wikipedia 客户端.jetstream-ios – 一款 Uber 的 MVC 框架.它同时提供了多用户实时通讯支持,一旦启动 JetStream 后端服务,通过 WebSocket 协议可以分分钟建立多用户实时通讯应用.DeckRocket – 在相同 WiFi 网络环境内,通过iPhone 控制并播放 Mac 中的 PDF 文档.ScanBook – 扫扫图书:可以扫描

iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLibrary 封装出通用的方法. 这里引用一下前文中对 PhotoKit 基本构成的介绍: PHAsset: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源 PHFetchOptions: 获取资源时的参数,可以传 nil,即使用系统默认值 PHAssetCo