因为项目的要求是全局的socket,  哪里都有可能使用到socket去发消息, 所以我把socket写在了单利里面

项目用的是 pod 'CocoaAsyncSocket'  三方库, 是异步的, 如果没有cocopods  那就去guthub下载一个

特别需要注意一点, 如果服务器一下连着发了好几条数据, 消息会阻塞. 明确来说是大部分的文章在发出一条数据之后只调用了一次[sock readDataWithTimeout:-1 tag:0]; 这个方法去手动接收. 类似于发一条才能收一条这种概念,所以我在每收到一条数据处理完后再次调用一次这个方法

1.建立单例类 (单利还不会的,那真的要去好好查了, 这里的单例可能说的不太详细)

.h文件

#import <Foundation/Foundation.h>

//导入头文件

#import "GCDAsyncSocket.h"

//遵循代理

@interface Singleton : NSObject<GCDAsyncSocketDelegate>

//全局socket

@property(nonatomic,strong) GCDAsyncSocket *socket;

//单例创建方法

//此类方法, 不管调用多少次. 都只会使用一个, 单利请谨慎使用

+(Singleton *)shareSingleton;

//socket连接

- (void)connectToServerWithHost:(NSString *)host AndPort:(int)port;

//socket发送消息

- (void)sendMassageWithData:(NSString *)data;

@end

.m文件

static Singleton * shareS = nil;

//单例实现方法

+ (Singleton *)shareSingleton{

if (shareS == nil) {

shareS = [[Singleton alloc]init];

}

return shareS;

}

//实现.h连接方法

- (void)connectToServerWithHost:(NSString *)host AndPort:(int)port{

//这个方法在下面 , host 是后台给的服务器地址,  port是端口

[self StartLiveBtnWithHost:host AndPort:port];

}

//实现发送消息方法

- (void)sendMassageWithData:(NSString *)str{

//这个方法是CocoaAsyncSocket 的方法,  str是其他地方调用的时候传来, 注意: 如果后台对socket消息有不同的要求,那么要沟通好, 比如消息头,消息体之类的

  NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];

[self.socket writeData:data withTimeout:1 tag:200];

}

#pragma mark 建立Socket连接

- (void)StartLiveBtnWithHost:(NSString *)host AndPort:(int )port{

NSLog(@"建立长连接");

//getProperIPWithAddress 是针对ipv6后, 做的处理 , 别急, 在下面

NSString * ipaddr = [self getProperIPWithAddress:host port:port];

//创建一个socket对象

GCDAsyncSocket * socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

//连接

NSError *error = nil;

[socket connectToHost:ipaddr onPort:port error:&error];

self.socket = socket;

if (error) {

NSLog(@"%@",error);

}

}

//针对ipv6网络环境下适配,ipv4环境直接使用原来的地址

- (NSString *)getProperIPWithAddress:(NSString *)ipAddr port:(UInt32)port

{

NSError *addresseError = nil;

NSArray *addresseArray = [GCDAsyncSocket lookupHost:ipAddr

port:port

error:&addresseError];

if (addresseError) {

NSLog(@"");

}

NSString *ipv6Addr = [[NSString alloc]init];

for (NSData *addrData in addresseArray) {

if ([GCDAsyncSocket isIPv6Address:addrData]) {

ipv6Addr = [GCDAsyncSocket hostFromAddress:addrData];

}

}

if (ipv6Addr.length == 0) {

ipv6Addr = ipAddr;

}

return ipv6Addr;

}

#pragma mark 连接成功

-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{

NSLog(@"%s",__func__);

//只要走了这个代理方法, 就说明连接已经成功

NSLog(@"连接成功");

}

#pragma mark 断开连接

-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{

//这里有两种情况,网络不畅时间太长连接失败, 或者用户退出正常断开, 我这里做了断开提示用户,并且相应的断线重连

if (err) {

NSLog(@"连接失败");

[self.socket disconnect];

//弹出提示框;

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"网络不畅断开连接,请检查重新连接" preferredStyle: UIAlertControllerStyleAlert];

UIAlertAction * action1 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

}];

UIAlertAction * action2 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

//这里就是重新调一下socket连接的方法, 以及一些其他操作,根据自己的需求来

[HttpRequest ReconnectOnloss];

}];

[alert addAction:action1];

[alert addAction:action2];

//弹出提示框;

[[self appRootViewController] presentViewController:alert animated:true completion:nil];

}

}else{

NSLog(@"正常断开");

[self.timer invalidate];

[self.socket disconnect];

UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"网络不畅断开连接,请检查重新连接" preferredStyle: UIAlertControllerStyleAlert];

UIAlertAction * action1 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

}];

UIAlertAction * action2 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

//这里就是重新调一下socket连接的方法, 以及一些其他操作,根据自己的需求来

     [HttpRequest ReconnectOnloss];

}];

[alert addAction:action1];

[alert addAction:action2];

//弹出提示框;

[[self appRootViewController] presentViewController:alert animated:true completion:nil];

}

}

#pragma mark 数据发送成功

-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{

NSLog(@"%s",__func__);

//发送完数据手动读取,-1不设置超时

[sock readDataWithTimeout:-1 tag:0];

}

#pragma mark 读取数据

-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{

//这里的data,就是实时收到的后台发来的消息, 如果服务器用了各种方式的加密, 还需要跟后台人员及时沟通

NSLog(@"-------------data:%@",data);

NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"--------------%@",receiverStr);

//在这里,或者在你的消息处理类里面调用, 这样就不用发, 也可以实时一直收到数据

  [sock readDataWithTimeout:-1 tag:0];

}

--------------------------------------------------------------------------------

//顺便加上调用发消息

//如果在单例里面发

[self sendMassageWithData:[NSString stringWithFormat:@"8014,%@",dic[@"mRoleID"]]];

//如果在其他类发

[[Singleton shareSingleton] sendMassageWithData:[NSString stringWithFormat:@"8014,%@",dic[@"mRoleID"]]];

//如果有哪里不对的地方请多多包涵,共同研究, 可能有些括号不全之类的.

iOS开发 socket, 全局socket的更多相关文章

  1. iOS开发网络篇—Socket编程

    一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程 ...

  2. iOS:iOS开发非常全的三方库、插件等等

    iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...

  3. iOS开发之资料收集

    github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自github:https://github ...

  4. iOS开发 非常全的三方库、插件、大牛博客等等

    UI 下拉刷新 EGOTableViewPullRefresh- 最早的下拉刷新控件. SVPullToRefresh- 下拉刷新控件. MJRefresh- 仅需一行代码就可以为UITableVie ...

  5. iOS - 开发类库

    开发类库   UI 项目名称 项目信息 1.MJRefresh 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能.可以自定义上下拉刷新的文字说明. ...

  6. iOS开发--iOS及Mac开源项目和学习资料

    文/零距离仰望星空(简书作者)原文链接:http://www.jianshu.com/p/f6cdbc8192ba著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 原文出处:codecl ...

  7. iOS开发常用第三方库

    UI 动画 网络相关 Model 其他 数据库 缓存处理 PDF 图像浏览及处理 摄像照相视频音频处理 响应式框架 消息相关 版本新API的Demo 代码安全与密码 测试及调试 AppleWatch ...

  8. iOS开发之即时通讯之Socket(AsyncSocket)

    1.AsyncSocket介绍 如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯. iOS中Socket编程的方式: BSD Socket: BSD Socket 是UNIX系统中 ...

  9. iOS 网络编程:socket

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

随机推荐

  1. JS入门(一)

    在学js之前,我们应该先清楚js是什么,js全称JavaScript.是一门基于对象和事件的,有安全性的脚本语言.所谓脚本语言,就是一行一行执行的,就像剧本一样,一句句的往下读.而对象和事件,则是js ...

  2. 1755: [Usaco2005 qua]Bank Interest

    1755: [Usaco2005 qua]Bank Interest Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 187  Solved: 162[Su ...

  3. pageRank算法 python实现

    一.什么是pagerank PageRank的Page可是认为是网页,表示网页排名,也可以认为是Larry Page(google 产品经理),因为他是这个算法的发明者之一,还是google CEO( ...

  4. React中父组件与子组件之间的数据传递和标准化的思考

    React中父组件与子组件之间的数据传递的的实现大家都可以轻易做到,但对比很多人的实现方法,总是会有或多或少的差异.在一个团队中,这种实现的差异体现了每个人各自的理解的不同,但是反过来思考,一个团队用 ...

  5. MySQL入门(上)

    1 课程回顾 自定义标签&编码实战 1)自定义标签步骤: 1.1 编写标签处理器类,继承SimpleTagSupport类,覆盖doTag方法 1.2 在WEB-INF目录下建立tld文件,在 ...

  6. 实现Unity编辑器模式下的旋转

    最近在做一个模型展示的项目,我的想法是根据滑动屏幕的x方向差值和Y方向的差值,来根据世界坐标下的X轴和Y轴进行旋转,但是实习时候总是有一些卡顿.在观察unity编辑器下的旋转之后,发现编辑器下的旋转非 ...

  7. 自适应滤波——线性预测(LPC)

    作者:桂. 时间:2017-03-26  10:12:07 链接:http://www.cnblogs.com/xingshansi/p/6621914.html 声明:欢迎被转载,不过记得注明出处哦 ...

  8. js复制内容到剪切板,兼容pc和手机端,支持Safari浏览器

      最近,一些项目中用到监听用户复制.剪切的操作. 案例1.在PC端,当用户获得一个京东卡的使用券,当用户使用ctrl + C复制得到的使用券时,将使用券的代号复制到粘贴板,以便于用户ctrl+v进行 ...

  9. UT源代码123

    (3)设计佣金问题的程序 commission方法是用来计算销售佣金的需求,手机配件的销售商,手机配件有耳机(headphone).手机壳(Mobile phone shell).手机贴膜(Cellp ...

  10. python 、mmap 实现内存数据共享

    import mmap mmap_file = None ##从内存中读取信息, def read_mmap_info(): global mmap_file mmap_file.seek(0) ## ...