在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框架的简单封装的更多相关文章

  1. Unity 游戏框架搭建 2019 (四十八/四十九) MonoBehaviourSimplify 中的消息策略完善&关于发送事件的简单封装

    MonoBehaviourSimplify 中的消息策略完善 在上一篇,笔者说,MonoBehaviourSimplify 中的消息策略还有一些小问题.我们在这篇试着解决一下. 先贴出来代码: usi ...

  2. web自动化框架—BasePage 类的简单封装

    优秀的框架都有属于自己的思想,在搭建web自动化测试框架时,我们通常都遵循 PO(Page Object)思想. 简单理解就是我们会把每个页面看成一个对象,一切皆对象,面向对象编码,这样会让我们更好的 ...

  3. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  4. Android--Retrofit+RxJava的简单封装(三)

    1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...

  5. PHP ORM框架与简单代码实现(转)

    对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据 ...

  6. MongoDB Python官方驱动 PyMongo 的简单封装

    最近,需要使用 Python 对 MongodB 做一些简单的操作,不想使用各种繁重的框架.出于可重用性的考虑,想对 MongoDB Python 官方驱动 PyMongo 做下简单封装,百度一如既往 ...

  7. SSH整合框架+mysql简单的实现

    SSH整合框架+mysql简单的实现 1. 框架整合原理: struts2整合Spring 两种: 一种struts2自己创建Action,自动装配Service : 一种 将Action交给Spri ...

  8. Express框架的简单使用

    Express框架的简单使用 这个框架是基于Node.js的框架平台 需要先安装node.js 安装完node.js后使用指令操作 npm init --yes 初始化 npm i express 安 ...

  9. 一篇文章带你了解网页框架——Vue简单入门

    一篇文章带你了解网页框架--Vue简单入门 这篇文章将会介绍我们前端入门级别的框架--Vue的简单使用 如果你以后想从事后端程序员,又想要稍微了解前端框架知识,那么这篇文章或许可以给你带来帮助 温馨提 ...

随机推荐

  1. Java和R齐头并进才是根本

    Java和R齐头并进才是根本  数据分析师的成长之路  http://www.slideshare.net/SanderMak/data-science-with-r-for-java-d

  2. Hierarchyid(层次结构)数据类型

    实例表结构 CREATE TABLE [dbo].[Emp]( ,), ), [Org] [hierarchyid], ) INSERT INTO Emp(Name,Org) VALUES('吴xx' ...

  3. 第一百一十一节,JavaScript,BOM浏览器对象模型

    JavaScript,BOM浏览器对象模型 学习要点: 1.window对象 2.location对象 3.history对象 BOM也叫浏览器对象模型,它提供了很多对象,用于访问浏览器的功能.BOM ...

  4. STS中Maven配置

    最近接触maven, 配置过程中记录一下. STS是解压版的,启动后,可以看到已经有了Maven插件, , 但是,STS也同时给你了一个Maven,但是通常不建议使用STS自带的maven.使用默认的 ...

  5. iOS开发The Operation couldn't be completed.(LaunchServicesError error 0.)的解决方法

    显示错误:The Operation couldn't be completed.(LaunchServicesError error 0.)解决办法:第1种方法.点击当前的模拟器,点击IOS Sim ...

  6. GlusterFS缺点分析[转]

    原文:http://blog.sina.com.cn/s/blog_6b89db7a0101gbcy.html GlusterFS(GNU ClusterFile System)是一个开源的分布式文件 ...

  7. img 鼠标滑上后图片放大,滑下后图片复原

    <style type="text/css">img{ -webkit-transition: ease .2s; transition: ease .2s; -web ...

  8. Zeppelin使用spark解释器

    Zeppelin为0.5.6 Zeppelin默认自带本地spark,可以不依赖任何集群,下载bin包,解压安装就可以使用. 使用其他的spark集群在yarn模式下. 配置: vi zeppelin ...

  9. Chapter 16_4 私密性

    在Lua面向对象编程的基础设计当中,没有提供私密性机制.但是可以用其他方法实现,从而获得对象的访问控制. 这种实现不常用,作为兴趣爱好,只做基本了解. 基本做法是:通过两个table来表示一个对象.一 ...

  10. G - 小晴天老师系列——可恶的墨水瓶

    G - 小晴天老师系列——可恶的墨水瓶 Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Othe ...