请教,郁闷死了androidasync socketSocket接收大的数据时就接收的不完整

C#语言 &&&&最新内容
C#语言 &&&&随机内容Socket通信连续接收数据不流畅,求解惑!!!
[问题点数:40分]
Socket通信连续接收数据不流畅,求解惑!!!
[问题点数:40分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2016年7月 .NET技术大版内专家分月排行榜第一
2016年6月 .NET技术大版内专家分月排行榜第二2016年3月 .NET技术大版内专家分月排行榜第二2016年1月 .NET技术大版内专家分月排行榜第二2015年12月 .NET技术大版内专家分月排行榜第二2015年2月 .NET技术大版内专家分月排行榜第二2015年1月 .NET技术大版内专家分月排行榜第二2014年11月 .NET技术大版内专家分月排行榜第二2014年5月 .NET技术大版内专家分月排行榜第二2014年4月 .NET技术大版内专家分月排行榜第二2012年2月 多媒体/设计/Flash/Silverlight 开发大版内专家分月排行榜第二
2016年7月 .NET技术大版内专家分月排行榜第一
2016年6月 .NET技术大版内专家分月排行榜第二2016年3月 .NET技术大版内专家分月排行榜第二2016年1月 .NET技术大版内专家分月排行榜第二2015年12月 .NET技术大版内专家分月排行榜第二2015年2月 .NET技术大版内专家分月排行榜第二2015年1月 .NET技术大版内专家分月排行榜第二2014年11月 .NET技术大版内专家分月排行榜第二2014年5月 .NET技术大版内专家分月排行榜第二2014年4月 .NET技术大版内专家分月排行榜第二2012年2月 多媒体/设计/Flash/Silverlight 开发大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。AsyncSocket_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
AsyncSocket
上传于||文档简介
&&A​s​y​n​c​S​o​c​k​e​t​ ​聊​天​程​序
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢&&国之画&&&&&&
&& &&&&&&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!iOS应用中使用AsyncSocket库处理Socket通信的用法讲解
作者:李刚
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了iOS应用中使用AsyncSocket库处理Socket通信的用法讲解,AsyncSocket同时支持TCP和UDP,文中展示了其建立断开连接及发送接收消息的操作,very好用,需要的朋友可以参考下
用socket可以实现像QQ那样发送即时消息的功能。客户端和服务端需要建立长连接,在长连接的情况下,发送消息。客户端可以发送心跳包来检测长连接。
在iOS开发中使用socket,一般都是用第三方库AsyncSocket,不得不承认这个库确实很强大。下载地址
AsyncSocket类是支持TCP的。
AsyncUdpSocket是支持UDP的。
AsyncSocket是封装了CFSocket和CFSteam的TCP/IP socket网络库。它提供了异步操作,本地cocoa类的基于delegate的完整支持。主要有以下特性:
队列的非阻塞的读和写,而且可选超时。你可以调用它读取和写入,它会当完成后告知你。
自动的socket接收。如果你调用它接收连接,它将为每个连接启动新的实例,当然,也可以立即关闭这些连接。
委托(delegate)支持。错误、连接、接收、完整的读取、完整的写入、进度以及断开连接,都可以通过委托模式调用。
基于run loop的,而不是线程的。虽然可以在主线程或者工作线程中使用它,但你不需要这样做。它异步的调用委托方法,使用NSRunLoop。委托方法包括socket的参数,可让你在多个实例中区分。
自包含在一个类中。你无需操作流或者socket,这个类帮你做了全部。
支持基于IPV4和IPV6的TCP流。
AsyncUdpSocket是UDP/IP socket网络库,包装自CFSocket。它的工作很像TCP版本,只不过是用于处理UDP的。它包括基于非阻塞队列的发送接收操作,完整的委托支持,基于runloop,自包含的类,以及支持IPV4和IPV6。
使用AsyncSocket的时候可以做一层封装,根据需求提供几个接口出来。比如:连接、断开连接、发送消息等等。还有接受消息,接受到的消息可以通过通知、代理、block等传出去。
下面简单介绍一下对AsyncSocket使用.一般来说,一个用户只需要建立一个socket长连接,所以可以用单例类方便使用。
定义单列类:LGSocketServe
LGSocketServe.h
//& LGSocketServe.h
//& AsyncSocketDemo
#import &Foundation/Foundation.h&
#import "AsyncSocket.h"
@interface LGSocketServe : NSObject&AsyncSocketDelegate&
+ (LGSocketServe *)sharedSocketS
LGSocketServe.m
//& LGSocketServe.m
//& AsyncSocketDemo
#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
建立socket长连接
LGSocketServe.h
@property (nonatomic, strong) AsyncSocket&&&&&&&& *&&&&&& // socket
//& socket连接
- (void)startConnectS
LGSocketServe.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];
&&& return 0;
宏定义一下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&&&&&&&&&&&& *heartT&& // 心跳计时器
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";
&&& NSData&& *data& = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
&&& [self.socket writeData:data withTimeout:1 tag:1];
在连接成功的回调方法里,启动定时器,每隔2秒向服务器发送固定的消息来检测长连接。(这个根据服务器的需要就可以了)
1,用户手动断开连接
LGSocketServe.h
// 断开socket连接
-(void)cutOffS
LGSocketServe.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
&&& } else {
&&&&&&& 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"];
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 androidasync socket 的文章

 

随机推荐