CocoaAsyncSocket框架的简单封装
在iOS开发中使用socket(CFNetwork),一般都是用第三方库AsyncSocket。
参考博客:http://my.oschina.net/worldligang/blog/396881?fromerr=WRR1ZAie
CocoaAsyncSocket的git下载地址:https://github.com/robbiehanson/CocoaAsyncSocket
下载CocoaAsyncSocket的文件,导入runloop中的AsyncSocket.h和AsyncSocket.m文件。
以下就是封装的CocoaAsyncSocket工具类DLSocketServe。
//
// DLSocketServe.h
// AsnycSocketDemo
//
// Created by wiseman on 15/12/23.
// Copyright (c) 2015年 wiseman. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AsyncSocket.h" enum{
SocketOfflineByServer, //服务器掉线
SocketOfflineByUser, //用户断开
SocketOfflineByWifiCut, //wifi 断开
}; @interface DLSocketServe : NSObject<AsyncSocketDelegate> @property (strong,nonatomic) AsyncSocket * socket; @property (retain,nonatomic) NSTimer *heartTimer; //心跳计时器 +(DLSocketServe *)sharedSocketServe; //socket连接
-(void)startConnetSocket; //断开socket连接
-(void)cutOffSocket; //发送消息
-(void)sendMessage:(id)message;
@end
//
// DLSocketServe.m
// AsnycSocketDemo
//
// Created by wiseman on 15/12/23.
// Copyright (c) 2015年 wiseman. All rights reserved.
// #define HOST @"192.168.1.1"
#define PORT 8080 #define TIME_OUT 20 //设置读取超时 -1 表示不会使用超时
#define READ_TIME_OUT -1 //设置写入超时 -1表示不会使用超时
#define WRITW_TIME_OUT -1
#define MAX_BUFFER 1024 #import "DLSocketServe.h" @implementation DLSocketServe static DLSocketServe *socketServe = nil; //创建一个单例方法
+(DLSocketServe *)sharedSocketServe{
//@synchronized 的作用是创建一个互斥锁,保证此时没有其它线程对self对象进行修改。这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其它线程访问,起到线程的保护作用。 一般在公用变量的时候使用,如单例模式或者操作类的static变量中使用。
@synchronized(self){
if(socketServe == nil) {
socketServe = [[[self class] alloc] init];
}
}
return socketServe;
} +(instancetype)allocWithZone:(struct _NSZone *)zone{
@synchronized(self){
if (socketServe == nil) {
socketServe = [super allocWithZone:zone];
return socketServe;
}
}
return nil;
} -(void)startConnetSocket{
self.socket = [[AsyncSocket alloc]initWithDelegate:self];
[self.socket setRunLoopModes:@[NSRunLoopCommonModes]];
if (![self SocketOpen:HOST port:PORT]) { }
} -(NSInteger)SocketOpen:(NSString *)addr port:(NSInteger)port{
if (!([self.socket isConnected])) {
NSError *error = nil;
[self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
}
return ;
} //发送消息
-(void)sendMessage:(id)message{
//向服务器发送数据
NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:cmdData withTimeout:WRITW_TIME_OUT tag:];
} #pragma mark - AsyncSocket代理
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
NSLog(@"这是异步返回的连接成功"); //通过定时器不断的发送消息,来检测长连接
self.heartTimer = [NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
[self.heartTimer fire];
} //心跳连接
-(void)checkLongConnectByServe{
//向服务器发送固定的消息,来检测长连接
NSString *longConnect = @"connect is here";
NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:data withTimeout: tag:];
} //断开连接
//1.用户手动断开连接
-(void)cutOffSocket{
self.socket.userData = SocketOfflineByUser;
//cutOffSocket 是用户断开连接之后,不在尝试重新连接
[self.socket disconnect];
} //2.wifi断开,socket断开连接
-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{ NSData * unreadData = [sock unreadData]; // ** This gets the current buffer
if(unreadData.length > ) {
// socket出错会回调onSocket:willDisconnectWithError:方法,可以通过unreadData来读取未来得及读取的buffer。
[self onSocket:sock didReadData:unreadData withTag:]; } else { //wifi断开之后,会回调onSocket:willDisconnectWithError:方法,err.code == 57,这个时候设置self.socket.userData = SocketOfflineByWifiCut
NSLog(@" willDisconnectWithError %ld err = %@",sock.userData,[err description]);
if (err.code == ) {
self.socket.userData = SocketOfflineByWifiCut;
} } } //重新连接
//socket断开之后会回调 在onSocketDidDisconnect回调方法里面,会根据self.socket.userData来判断是否需要重新连接。
-(void)onSocketDidDisconnect:(AsyncSocket *)sock{
NSLog(@"%ld",sock.userData);
if (sock.userData == SocketOfflineByServer) {
//服务器掉线,重连
[self startConnetSocket];
}
else if (sock.userData == SocketOfflineByUser){
//如果由用户断开,不进行重连
return;
}
else if (sock.userData == SocketOfflineByWifiCut){
//wifi断开,不进行重连
return;
}
} //发送消息成功之后回调
-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{
//发送消息成功之后会调用onSocket:didWriteDataWithTag:,在这个方法里可以进行读取消息。
//读取消息
[self.socket readDataWithTimeout:- buffer:nil bufferOffset: maxLength:MAX_BUFFER tag:];
} //接受消息成功之后回调
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
//服务端返回消息数据量比较大时,可能分多次返回。所以在读取消息的时候,设置MAX_BUFFER表示每次最多读取多少,当data.length < MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析 if (data.length < MAX_BUFFER) {
//收到结果解析
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dic);
//解析出来的消息,可以通过通知,代理,block等传递出去 } [self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset: maxLength:MAX_BUFFER tag:]; } - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
NSLog(@"didAcceptNewSocket");
} @end
封装好之后,使用:
导入:#import "DLSocketServe.h"
DLSocketServe *socketServe = [DLSocketServe sharedSocketServe];
//socket连接前先断开连接以免之前socket连接没有断开导致闪退
[socketServe cutOffSocket];
socketServe.socket.userData = SocketOfflineByServer;
[socketServe startConnectSocket]; //发送消息 @"hahaha"只是举个列子,具体根据服务端的消息格式
[socketServe sendMessage:@"hahaha"];
CocoaAsyncSocket框架的简单封装的更多相关文章
- Unity 游戏框架搭建 2019 (四十八/四十九) MonoBehaviourSimplify 中的消息策略完善&关于发送事件的简单封装
MonoBehaviourSimplify 中的消息策略完善 在上一篇,笔者说,MonoBehaviourSimplify 中的消息策略还有一些小问题.我们在这篇试着解决一下. 先贴出来代码: usi ...
- web自动化框架—BasePage 类的简单封装
优秀的框架都有属于自己的思想,在搭建web自动化测试框架时,我们通常都遵循 PO(Page Object)思想. 简单理解就是我们会把每个页面看成一个对象,一切皆对象,面向对象编码,这样会让我们更好的 ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- Android--Retrofit+RxJava的简单封装(三)
1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...
- PHP ORM框架与简单代码实现(转)
对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据 ...
- MongoDB Python官方驱动 PyMongo 的简单封装
最近,需要使用 Python 对 MongodB 做一些简单的操作,不想使用各种繁重的框架.出于可重用性的考虑,想对 MongoDB Python 官方驱动 PyMongo 做下简单封装,百度一如既往 ...
- SSH整合框架+mysql简单的实现
SSH整合框架+mysql简单的实现 1. 框架整合原理: struts2整合Spring 两种: 一种struts2自己创建Action,自动装配Service : 一种 将Action交给Spri ...
- Express框架的简单使用
Express框架的简单使用 这个框架是基于Node.js的框架平台 需要先安装node.js 安装完node.js后使用指令操作 npm init --yes 初始化 npm i express 安 ...
- 一篇文章带你了解网页框架——Vue简单入门
一篇文章带你了解网页框架--Vue简单入门 这篇文章将会介绍我们前端入门级别的框架--Vue的简单使用 如果你以后想从事后端程序员,又想要稍微了解前端框架知识,那么这篇文章或许可以给你带来帮助 温馨提 ...
随机推荐
- hdu 1839 Delay Constrained Maximum Capacity Path
最短路+二分. 对容量进行二分,因为容量和时间是单调关系的,容量越多,能用的边越少,时间会不变或者增加. 因为直接暴力一个一个容量去算会TLE,所以采用二分. #include<cstdio&g ...
- flask部署 supervisor的使用
安装supervisor sudo apt-get install supervsor 配置 打开 /etc/supervisor/supervisor.conf 可以看到 同目录文件夹下的 co ...
- Python学习笔记_Chapter 7web开发
1.web应用元素 a.成员: web浏览器 web服务器 b.行为: web请求: 请求内容: 静态内容:如html文件,图像. 动态内容:需服务器运行一个程序进而做出响应. 网关接口&CG ...
- reshape2 数据操作 数据融合( cast)
我们在做数据分析的时候,对数据进行操作也是一项极其重要的内容,这里我们同样介绍强大包reshape2,其中的几个函数,对数据进行操作cast和melt两个函数绝对少不了. 首先是cast,把长型数据转 ...
- ggplot2 theme相关设置—文本调整
在geom设置和scale设置之后,要想把图画的漂亮,theme设置是比不可少的 在theme 设置中element_text()是一项很重要的内容 element_text(family = NUL ...
- hdu_5969_最大的位或(贪心)
题目链接:hdu_5969_最大的位或 题意: 中文,还是自己看 题解: xjb贪心一下就行了 #include<bits/stdc++.h> #define F(i,a,b) for(i ...
- MongoDB文档基本操作
一.插入文档 使用insert()或save()方法向集合插入文档 >db.COLLECTION_NAME.insert(document) 详细用法可以参考MongoDB菜鸟教程 二.查找文档 ...
- vultr vps发布多用户管理功能
中国用户购买海外vps,有一个麻烦之处是付款环节,可能你没有visa信用卡,vultr和digitalocean和linode这类vps不支持支付宝,给一些朋友带来不便.由此产生的vps代购行业,其实 ...
- OC类的本质及分类
(一)类的本质 类对象(class object)与实例对象(instance object) 类本身也是一个对象,是class类型的对象,简称“类对象”. 在/usr/include/objc/ob ...
- 归并排序的go语言与C++实现对比
最近对go语言发生了兴趣,发现go语言语法简洁,非常适合算法的描述和实现,于是对归并排序进行了实现. 例子中需要排序的队列是长度为100的从100到1的数列,排序算法是正序排序,排序正确的话,结果应当 ...