求助 在ios上java socket断线重连响应很慢

转自芳仔小脚印&
http://my.oschina.net/joanfen/blog/287238?p=2#comments
如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯,本人也是刚学习,分享一下,有什么不对的地方希望大家指正
ios原生的socket用起来不是很直观,所以我用的是AsyncSocket这个第三方库,对socket的封装比较好,只是好像没有带外传输(out—of-band) 如果你的服务器需要发送带外数据,可能得想下别的办法
下载AsyncSocket类库,将RunLoop文件夹下的AsyncSocket.h,
AsyncSocket.m, AsyncUdpSocket.h, AsyncUdpSocket.m 文件拷贝到自己的project中
添加CFNetwork.framework, 在使用socket的文件头
1. socket 连接
即时通讯最大的特点就是实时性,基本感觉不到延时或是掉线,所以必须对socket的连接进行监视与检测,在断线时进行重新连接,如果用户退出登录,要将socket手动关闭,否则对服务器会造成一定的负荷。
一般来说,一个用户(对于ios来说也就是我们的项目中)只能有一个正在连接的socket,所以这个socket变量必须是全局的,这里可以考虑使用单例或是AppDelegate进行数据共享,本文使用单例。如果对一个已经连接的socket对象再次进行连接操作,会抛出异常(不可对已经连接的socket进行连接)程序崩溃,所以在连接socket之前要对socket对象的连接状态进行判断
使用socket进行即时通讯还有一个必须的操作,即对服务器发送心跳包,每隔一段时间对服务器发送长连接指令(指令不唯一,由服务器端指定,包括使用socket发送消息,发送的数据和格式都是由服务器指定),如果没有收到服务器的返回消息,AsyncSocket会得到失去连接的消息,我们可以在失去连接的回调方法里进行重新连接。
先创建一个单例,命名为Singleton
&span style=&color:#ff6666;&&// Singleton.h文件&/span&&span style=&color: rgb(51, 51, 51);&&
#import &AsyncSocket.h&
#define DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \
static dispatch_once_t onceToken = 0; \
__strong static id sharedInstance = \
dispatch_once(&onceToken, ^{ \
sharedInstance = block(); \
return sharedI \
@interface Singleton : NSObject
+ (Singleton *)sharedI
@end&/span&
//Singleton.m文件
+(Singleton *) sharedInstance
static Singleton *sharedInstace =
static dispatch_once_t onceT
dispatch_once(&onceToken, ^{
sharedInstace = [[self alloc] init];
return sharedI
这样一个单例就创建好了
在.h文件中生命socket变量
@property (nonatomic, strong) AsyncSocket
@property (nonatomic, copy
) NSString
// socket的Host
@property (nonatomic, assign) UInt16
// socket的prot
下面是连接,心跳,失去连接后重连
连接(长连接)
在.h文件中声明方法,并声明代理&AsyncSocketDelegate&
-(void)socketConnectH// socket连接
在.m中实现,连接时host与port都是由服务器指定,如果不是自己写的服务器,请与服务器端开发人员交流
// socket连接
-(void)socketConnectHost{
self.socket
= [[AsyncSocket alloc] initWithDelegate:self];
NSError *error =
[self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error];
}&/pre&&pre name=&code& class=&objc&&&p style=&padding-top: 0 padding-bottom: 0 margin-top: 8 margin-bottom: 8 line-height: 22.5 letter-spacing: 0.5 font-size: 13 word-wrap: break- word-break: break- color: rgb(51, 51, 51); font-family: Verdana, sans-serif, 宋体;&&&span style=&padding: 0 margin: 0&&心跳&/span&&/p&&p style=&padding-top: 0 padding-bottom: 0 margin-top: 8 margin-bottom: 8 line-height: 22.5 letter-spacing: 0.5 font-size: 13 word-wrap: break- word-break: break- color: rgb(51, 51, 51); font-family: Verdana, sans-serif, 宋体;&&心跳通过计时器来实现 &br style=&padding: 0 margin: 0& /&在singleton.h中声明一个定时器&/p&&pre name=&code& class=&objc&&@property (nonatomic, retain) NSTimer
*connectT // 计时器
在.m中实现连接成功回调方法,并在此方法中初始化定时器,发送心跳在后文向服务器发送数据时说明
&span style=&color: rgb(51, 51, 51); font-family: Verdana, sans-serif, 宋体; font-size: 13 letter-spacing: 0.5 line-height: 22.5&&&/span&&pre name=&code& class=&objc&&#pragma mark
- 连接成功回调
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString
*)host port:(UInt16)port
NSLog(@&socket连接成功&);
// 每隔30s像服务器发送心跳包
self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];// 在longConnectToSocket方法中进行长连接需要向服务器发送的讯息
[self.connectTimer fire];
2. socket 断开连接与重连
失去连接有几种情况,服务器断开,用户主动cut,还可能有如QQ其他设备登录被掉线的情况,不管那种情况,我们都能收到socket回调方法返回给我们的讯息,如果是用户退出登录或是程序退出而需要手动cut,我们在cut前对socket的userData赋予一个值来标记为用户退出,这样我们可以在收到断开信息时判断究竟是什么原因导致的掉线
在.h文件中声明一个枚举类型
SocketOfflineByServer,// 服务器掉线,默认为0
SocketOfflineByUser,
// 用户主动cut
};声明断开连接方法
-(void)cutOffS // 断开socket连接&/pre&&pre name=&code& class=&objc&&在.m文件实现&/pre&&pre name=&code& class=&objc&&// 切断socket
-(void)cutOffSocket{
self.socket.userData = SocketOfflineByU// 声明是由用户主动切断
[self.connectTimer invalidate];
[self.socket disconnect];
实现代理方法
-(void)onSocketDidDisconnect:(AsyncSocket *)sock
NSLog(@&sorry the connect is failure %ld&,sock.userData);
if (sock.userData == SocketOfflineByServer) {
// 服务器掉线,重连
[self socketConnectHost];
else if (sock.userData == SocketOfflineByUser) {
// 如果由用户断开,不进行重连
3. socket 发送与接收数据
我们补充上文心跳连接未完成的方法
// 心跳连接
-(void)longConnectToSocket{
// 根据服务器要求发送固定格式的数据,假设为指令@&longConnect&,但是一般不会是这么简单的指令
NSString *longConnect = @&longConnect&;
*dataStream
= [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:dataStream withTimeout:1 tag:1];
socket发送数据是以栈的形式存放,所有数据放在一个栈中,存取时会出现粘包的现象,所以很多时候服务器在收发数据时是以先发送内容字节长度,再发送内容的形式,得到数据时也是先得到一个长度,再根据这个长度在栈中读取这个长度的字节流,如果是这种情况,发送数据时只需在发送内容前发送一个长度,发送方法与发送内容一样,假设长度为8
*dataStream
= [@8 dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:dataStream withTimeout:1 tag:1];
为了能时刻接收到socket的消息,我们在长连接方法中进行读取数据
[self.socket readDataWithTimeout:30 tag:0];
如果得到数据,会调用回调方法
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
// 对得到的data值进行解析与转换即可
[self.socket readDataWithTimeout:30 tag:0];
4. 简单使用说明
我们在用户登录后的第一个界面进行socket的初始化连接操作,在得到数据后,将所需要显示的数据放在singleton中,对变量进行监听后做出相应的操作即可,延伸起来比较复杂,没有真实数据也不太方便说明,大家自己进行探索吧,有问题请在下方留言
[Singleton sharedInstance].socketHost = @&192.186.100.21&;// host设定
[Singleton sharedInstance].socketPort = 10045;// port设定
// 在连接前先进行手动断开
[Singleton sharedInstance].socket.userData = SocketOfflineByU
[[Singleton sharedInstance] cutOffSocket];
// 确保断开后再连,如果对一个正处于连接状态的socket进行连接,会出现崩溃
[Singleton sharedInstance].socket.userData = SocketOfflineByS
[[Singleton sharedInstance] socketConnectHost];
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:15892次
排名:千里之外
原创:23篇
转载:20篇
(1)(1)(2)(5)(2)(3)(11)(13)(6)6844人阅读
以前在iphone上写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。
client端通过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client 端时就产生Broken pipe 信号了。
对于产生信号,我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。
如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。
我们可以调用系统的处理方法,也可以自定义处理方法。
以前不清楚的时候,程序莫名其妙的崩溃不了解,后来才了解到,在代码中进行了以下处理后app就不会崩溃了。
/***************************************************/
//设置不被SIGPIPE信号中断,物理链路损坏时才不会导致程序直接被Terminate
//在网络异常的时候如果程序收到SIGPIRE是会直接被退出的。
sa.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &sa, 0 );
/***************************************************/
以下是从网络中整理的一些相关资料:
1)&& SIGHUP&& 2)&& SIGINT&& 3)&& SIGQUIT&& 4)&& SIGILL
5)&& SIGTRAP&& 6)&& SIGABRT&& 7)&& SIGEMT&& 8)&& SIGFPE
9)&& SIGKILL&& 10)&& SIGBUS&& 11)&& SIGSEGV&& 12)&& SIGSYS
13)&& SIGPIPE&& 14)&& SIGALRM&& 15)&& SIGTERM&& 16)&& SIGUSR1
17)&& SIGUSR2&& 18)&& SIGCHLD&& 19)&& SIGPWR&& 20)&& SIGWINCH
21)&& SIGURG&& 22)&& SIGIO&& 23)&& SIGSTOP&& 24)&& SIGTSTP
25)&& SIGCONT&& 26)&& SIGTTIN&& 27)&& SIGTTOU&& 28)&& SIGVTALRM
29)&& SIGPROF&& 30)&& SIGXCPU&& 31)&& SIGXFSZ&& 32)&& SIGWAITING
33)&& SIGLWP&& 34)&& SIGFREEZE&& 35)&& SIGTHAW&& 36)&& SIGCANCEL
37)&& SIGLOST&& 39)&& SIGRTMIN&& 40)&& SIGRTMIN+1&& 41)&& SIGRTMIN+2
42)&& SIGRTMIN+3&& 43)&& SIGRTMAX-3&& 44)&& SIGRTMAX-2&& 45)&& SIGRTMAX-1
46)&& SIGRTMAX
下面是一些信号说明
1)&& SIGHUP
本信号在用户终端连接(正常或非正常)结束时发出,&& 通常是在终端的控制进程结束时,&& 通知同一session内的各个作业,&& 这时它们与控制终端不再关联。
登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都属于这个&&&& Session。当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进&& 程组和后台有终端输出的进程就会中止。不过可以捕获这个信号,比如wget能捕获SIGHUP信号,并忽略它,这样就算退出了Linux登录,&& wget也&& 能继续下载。
此外,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。
2)&& SIGINT
程序终止(interrupt)信号,&& 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。
3)&& SIGQUIT
和SIGINT类似,&& 但由QUIT字符(通常是Ctrl-\)来控制.&& 进程在因收到SIGQUIT退出时会产生core文件,&& 在这个意义上类似于一个程序错误信号。
4)&& SIGILL
执行了非法指令.&& 通常是因为可执行文件本身出现错误,&& 或者试图执行数据段.&& 堆栈溢出时也有可能产生这个信号。
5)&& SIGTRAP
由断点指令或其它trap指令产生.&& 由debugger使用。
6)&& SIGABRT
调用abort函数生成的信号。
7)&& SIGBUS
非法地址,&& 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数,&& 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间)。
8)&& SIGFPE
在发生致命的算术运算错误时发出.&& 不仅包括浮点运算错误,&& 还包括溢出及除数为0等其它所有的算术的错误。
9)&& SIGKILL
用来立即结束程序的运行.&& 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。
10)&& SIGUSR1
留给用户使用
11)&& SIGSEGV
试图访问未分配给自己的内存,&& 或试图往没有写权限的内存地址写数据.
12)&& SIGUSR2
留给用户使用
13)&& SIGPIPE
管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止。
14)&& SIGALRM
时钟定时信号,&& 计算的是实际的时间或时钟时间.&& alarm函数使用该信号.
15)&& SIGTERM
程序结束(terminate)信号,&& 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号。如果进程终止不了,我们才会尝试SIGKILL。
17)&& SIGCHLD
子进程结束时,&& 父进程会收到这个信号。
如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程称为僵尸进程。这种情&&&& 况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,这时子进程的终止自动由init进程&& 来接管)。
18)&& SIGCONT
让一个停止(stopped)的进程继续执行.&& 本信号不能被阻塞.&& 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定的工作.&& 例如,&& 重新显示提示符
19)&& SIGSTOP
停止(stopped)进程的执行.&& 注意它和terminate以及interrupt的区别:该进程还未结束,&& 只是暂停执行.&& 本信号不能被阻塞,&& 处理或忽略.
20)&& SIGTSTP
停止进程的运行,&& 但该信号可以被处理和忽略.&& 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号
21)&& SIGTTIN
当后台作业要从用户终端读数据时,&& 该作业中的所有进程会收到SIGTTIN信号.&& 缺省时这些进程会停止执行.
22)&& SIGTTOU
类似于SIGTTIN,&& 但在写终端(或修改终端模式)时收到.
23)&& SIGURG
有”紧急”数据或out-of-band数据到达socket时产生.
24)&& SIGXCPU
超过CPU时间资源限制.&& 这个限制可以由getrlimit/setrlimit来读取/改变。
25)&& SIGXFSZ
当进程企图扩大文件以至于超过文件大小资源限制。
26)&& SIGVTALRM
虚拟时钟信号.&& 类似于SIGALRM,&& 但是计算的是该进程占用的CPU时间.
27)&& SIGPROF
类似于SIGALRM/SIGVTALRM,&& 但包括该进程用的CPU时间以及系统调用的时间.
28)&& SIGWINCH
窗口大小改变时发出.
29)&& SIGIO
文件描述符准备就绪,&& 可以开始进行输入/输出操作.
30)&& SIGPWR
Power&& failure
31)&& SIGSYS
非法的系统调用。
在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP
不能恢复至默认动作的信号有:SIGILL,SIGTRAP
默认会导致进程流产的信号有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ
默认会导致进程退出的信号有:SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM
默认会导致进程停止的信号有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU
默认进程忽略的信号有:SIGCHLD,SIGPWR,SIGURG,SIGWINCH
此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;SIGCONT在进程挂起时是继续,否则是忽略,不能被阻塞。
大部分的信号都能中断socket程序。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:563657次
积分:6258
积分:6258
排名:第3081名
原创:90篇
评论:195条
(2)(4)(4)(7)(4)(1)(7)(13)(2)(2)(19)(3)(2)(5)(14)(10)(3)(1)(1)匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。用socket可以实现像QQ那样发送即时消息的功能。客户端和服务端需要建立长连接,在长连接的情况下,发送消息。客户端可以发送心跳包来检测长连接。在iOS开发中使用socket,一般都是用第三方库AsyncSocket,不得不承认这个库确实很强大。下载地址/robbiehanson/CocoaAsyncSocket.git。使用AsyncSocket的时候可以做一层封装,根据需求提供几个接口出来。比如:连接、断开连接、发送消息等等。还有接受消息,接受到的消息可以通过通知、代理、block等传出去。简单介绍一下对AsyncSocket使用.一般来说,一个用户只需要建立一个socket长连接,所以可以用单例类方便使用。定义单列类:LGSocketServeLGSocketServe.h//
LGSocketServe.h
AsyncSocketDemo
Created by ligang on 15/4/3.
Copyright (c) 2015年 ligang. All rights reserved.
#import &Foundation/Foundation.h&
#import &AsyncSocket.h&
@interface LGSocketServe : NSObject&AsyncSocketDelegate&
+ (LGSocketServe *)sharedSocketS
@endLGSocketServe.m//
LGSocketServe.m
AsyncSocketDemo
Created by ligang on 15/4/3.
Copyright (c) 2015年 ligang. All rights reserved.
#import &LGSocketServe.h&
@implementation LGSocketServe
static LGSocketServe *socketServe =
#pragma mark public static methods
+ (LGSocketServe *)sharedSocketServe {
@synchronized(self) {
if(socketServe == nil) {
socketServe = [[[self class] alloc] init];
return socketS
+(id)allocWithZone:(NSZone *)zone
@synchronized(self)
if (socketServe == nil)
socketServe = [super allocWithZone:zone];
return socketS
@end建立socket长连接LGSocketServe.h@property (nonatomic, strong) AsyncSocket
socket连接
- (void)startConnectSLGSocketServe.m//自己设定
#define HOST @&192.168.0.1&
#define PORT 8080
//设置连接超时
#define TIME_OUT 20
- (void)startConnectSocket
self.socket = [[AsyncSocket alloc] initWithDelegate:self];
[self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
if ( ![self SocketOpen:HOST port:PORT] )
- (NSInteger)SocketOpen:(NSString*)addr port:(NSInteger)port
if (![self.socket isConnected])
NSError *error =
[self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
}宏定义一下HOST、PORT、TIME_OUT,实现startConnectSocket方法。这个时候要设置一下AsyncSocket的代理AsyncSocketDelegate。当长连接成功之后会调用:- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
//这是异步返回的连接成功,
NSLog(@&didConnectToHost&);
}心跳LGSocketServe.h@property (nonatomic, retain) NSTimer
// 心跳计时器LGSocketServe.m- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
//这是异步返回的连接成功,
NSLog(@&didConnectToHost&);
//通过定时器不断发送消息,来检测长连接
self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
[self.heartTimer fire];
// 心跳连接
-(void)checkLongConnectByServe{
// 向服务器发送固定可是的消息,来检测长连接
NSString *longConnect = @&connect is here&;
= [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:data withTimeout:1 tag:1];
}在连接成功的回调方法里,启动定时器,每隔2秒向服务器发送固定的消息来检测长连接。(这个根据服务器的需要就可以了)断开连接1,用户手动断开连接LGSocketServe.h// 断开socket连接
-(void)cutOffSLGSocketServe.m-(void)cutOffSocket
self.socket.userData = SocketOfflineByU
[self.socket disconnect];
}cutOffSocket是用户断开连接之后,不在尝试重新连接。2,wifi断开,socket断开连接LGSocketServe.m- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
NSLog(@& willDisconnectWithError %ld
err = %@&,sock.userData,[err description]);
if (err.code == 57) {
self.socket.userData = SocketOfflineByWifiC
}wifi断开之后,会回调onSocket:willDisconnectWithError:方法,err.code == 57,这个时候设置self.socket.userData = SocketOfflineByWifiCut。重新连接socket断开之后会回调:LGSocketServe.m- (void)onSocketDidDisconnect:(AsyncSocket *)sock
NSLog(@&7878 sorry the connect is failure %ld&,sock.userData);
if (sock.userData == SocketOfflineByServer) {
// 服务器掉线,重连
[self startConnectSocket];
else if (sock.userData == SocketOfflineByUser) {
// 如果由用户断开,不进行重连
}else if (sock.userData == SocketOfflineByWifiCut) {
// wifi断开,不进行重连
}在onSocketDidDisconnect回调方法里面,会根据self.socket.userData来判断是否需要重新连接。发送消息LGSocketServe.h// 发送消息
- (void)sendMessage:(id)LGSocketServe.m//设置写入超时 -1 表示不会使用超时
#define WRITE_TIME_OUT -1
- (void)sendMessage:(id)message
//像服务器发送数据
NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:cmdData withTimeout:WRITE_TIME_OUT tag:1];
//发送消息成功之后回调
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
}发送消息成功之后会调用onSocket:didWriteDataWithTag:,在这个方法里可以进行读取消息。接受消息LGSocketServe.m//设置读取超时 -1 表示不会使用超时
#define READ_TIME_OUT -1
#define MAX_BUFFER 1024
//发送消息成功之后回调
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
//读取消息
[self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
//接受消息成功之后回调
- (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:0 maxLength:MAX_BUFFER tag:0];接受消息后去解析,然后可以通过通知、代理、block等传出去。在onSocket:didReadData:withTag:回调方法里面需要
不断读取消息,因为数据量比较大的话,服务器会分多次返回。所以我们需要定义一个MAX_BUFFER的宏,表示每次最多读取多少。当
data.length & MAX_BUFFER我们认为有可能是接受完一个完整的消息,然后才解析
。出错处理LGSocketServe.m- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
NSData * unreadData = [sock unreadData]; // ** This gets the current buffer
if(unreadData.length & 0) {
[self onSocket:sock didReadData:unreadData withTag:0]; // ** Return as much data that could be collected
NSLog(@& willDisconnectWithError %ld
err = %@&,sock.userData,[err description]);
if (err.code == 57) {
self.socket.userData = SocketOfflineByWifiC
}socket出错会回调onSocket:willDisconnectWithError:方法,可以通过unreadData来读取未来得及读取的buffer。使用导入#import “LGSocketServe.h” LGSocketServe *socketServe = [LGSocketServe sharedSocketServe];
//socket连接前先断开连接以免之前socket连接没有断开导致闪退
[socketServe cutOffSocket];
socketServe.socket.userData = SocketOfflineByS
[socketServe startConnectSocket];
//发送消息 @&hello world&只是举个列子,具体根据服务端的消息格式
[socketServe sendMessage:@&hello world&];以上是AsyncSocket的简单使用,在实际开发过程中依然会碰到很多问题,欢迎加我的微信公众号iOS开发:iOSDevTip,一起讨论AsyncSocket中遇到的问题。●本文编号97,以后想阅读这篇文章直接输入97即可。●本文分类“AsyncSocket、socket”,直接回复分类名可以获得相关文章。●输入m可以获取到全部文章目录如果你觉得iOS开发公众微信对你有帮助,请点击右上角“...”标志分享到【朋友圈】,感谢支持!合作请联系微信:chinaligang
iOS开发(iOSDevTip) 
 文章为作者独立观点,不代表大不六文章网立场
iOSDevTip最新iOS、iPhone资讯,万名iOS开发者、swift开发、果粉聚集,参与技术讨论,整理开发技巧,分享创业经验!享受生活、热爱编程!热门文章最新文章iOSDevTip最新iOS、iPhone资讯,万名iOS开发者、swift开发、果粉聚集,参与技术讨论,整理开发技巧,分享创业经验!享受生活、热爱编程!&&&&违法和不良信息举报电话:183-
举报邮箱:
Copyright(C)2016 大不六文章网
京公网安备78

我要回帖

更多关于 websocket 断线 的文章

 

随机推荐