在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. noip2015Day2T2-子串

    题目描述 Description 有两个仅包含小写英文字母的字符串A和B.现在要从字符串A中取出k个互不重叠的非空子串,然后把这k个子串按照其在字符串A中出现的顺序依次连接起来得到一个新的字符串,请问 ...

  2. L2-012. 关于堆的判断

    L2-012. 关于堆的判断 题目链接:https://www.patest.cn/contests/gplt/L2-012 终于ac了,简直要哭.题目还是很简单的,不过很多坑: 1.寻找x下标时,有 ...

  3. sqlalchemy 映射的小例子

    1.多张表映射到一个类 import pandas as pdfrom settings import DATABASESfrom sqlalchemy import create_engineimp ...

  4. document.body 和 document.documentElement 的区别

    document.body 和 document.documentElement 的区别 : www.cnblogs.com/scy251147/archive/2011/04/10/2011420. ...

  5. 2016年团体程序设计天梯赛-决赛 L1-3. 出租(20)

    下面是新浪微博上曾经很火的一张图: 一时间网上一片求救声,急问这个怎么破.其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1,index[1]=0 对 ...

  6. 使用 Spark MLlib 做 K-means 聚类分析[转]

    原文地址:https://www.ibm.com/developerworks/cn/opensource/os-cn-spark-practice4/ 引言 提起机器学习 (Machine Lear ...

  7. SSL单向认证和双向认证原理

    注:本文为个人学习摘录,原文地址:http://edison0663.iteye.com/blog/996526 为了便于更好的认识和理解 SSL 协议,这里着重介绍 SSL 协议的握手协议.SSL ...

  8. Ubuntu环境变量——系统变量和用户变量

    系统变量: 对所有用户有效果 /etc/profile /etc/environment 两个命令只用一个就可以,原则上是重启后修改生效,但是经过验证可以通过执行以下命令实现: source /etc ...

  9. sql优化原则

    尽量使用性能高的比如left join等,尽量减少数据查询的column,尽量不要查询冗余数据,like的话“%%”是没有 办法使用索引的,但是“%”是可以使用索引的 having以前一直不知道到底真 ...

  10. socket编程,简单多线程服务端测试程序

    socket编程,简单多线程服务端测试程序 前些天重温了MSDN关于socket编程的WSAStartup.WSACleanup.socket.closesocket.bind.listen.acce ...