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的简单使用 如果你以后想从事后端程序员,又想要稍微了解前端框架知识,那么这篇文章或许可以给你带来帮助 温馨提 ...
随机推荐
- 微信小程序Tabbar文字在真机不显示
按照官方文档在json中定义好了Tabbar后,在模拟器上显示没问题,而在真机上不显示Tabar文字. 让我很苦笑不得的原因是: 在app.json定义Tabbar文字选中态和非选中态颜色时我用了英文 ...
- git的使用,将本地项目push到github上
Git教程(推荐): http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000git是先用a ...
- Firebug入门指南
据说,对于网页开发人员来说,Firebug是Firefox浏览器中最好的插件之一. 我最近就在学习怎么使用Firebug,网上找到一篇针对初学者的教程,感觉比较有用,就翻译了出来. ========= ...
- css ::before和::after伪元素的用法
css ::before和::after伪元素的用法:http://blog.dimpurr.com/css-before-after/
- java 视频中截图
package com.sun.test; import java.io.File; import java.util.List; public class CreatePh { //public s ...
- Python处理Excel(转载)
1. Python 操作 Excel 的函数库 我主要尝试了 3 种读写 Excel 的方法: 1> xlrd, xlwt, xlutils: 这三个库的好处是不需要其它支持,在任何操作系统上都 ...
- 深入理解Java内存模型 - volatile
volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这 ...
- 可靠通信的保障 —— 使用ACK机制发送自定义信息——ESFramework 通信框架4.0 快速上手(12)
使用ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoOutter接口的Send方法,我们已经可以给服务端或其它在线客户端发送自定义信息了, ...
- 不创建类将json数据转换
一般,取到json数据之后,都会将json数据转换为对象,通过属性取得里面的属性值,这样做可以很好地利用vs的智能提示,让开发更轻松,但是代价就是,你需要手动的创建json数据相对应的类. 也有其他方 ...
- Excel教程(4) - 数据库函数
DAVERAGE 用途:返回数据库或数据清单中满足指定条件的列中数值 的平均值. 语法:DAVERAGE(database,field,criteria) 参数:Database 构成 ...