AsyncSocket didReadData函数详解

恐怕在AsyncSocket框架中,最关键的一个函数要数

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;

这个函数在socket输入流获取到数据时被调用,也可以自定义timeout和length。本文重点讨论这个基本函数使用中容易出现的问题。如果socket使用没有问题,基本上读取到数据没有问题,但是如果服务器发送了多个socket请求,导致didReadData函数被反复调用,并且不知道什么时候是最后一次请求。

因为服务器端和客户端对socket的处理不一样,所以先来看看在客户端,didReadData函数的用法。
首先要在方法的最后设置读取数据超时时间。

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    //…………
    //前面是各种处理
    [client readDataWithTimeout:-1 tag:0];
}

这样,socket会不断获取数据,直到数据被完全获取为止。
但是,程序员怎么知道数据已经全部被获取到了呢?我们需要另外添加一个变量来实现这个功能。

@property (nonatomic, retain) NSMutableData *receiveData;

我们定义了一个NSMutableData类型的data,然后每次获取到数据的时候,就把获取到的数据附加到receiveData上,并且判断数据是否已经读取完成。因此,我们把didReadData修改如下:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    if (receiveData == nil) {
        //如果不存在,则创建一个新的
        receiveData = [[NSMutableData alloc] init];
    }
    [receiveData appendData:data];//把接收到的数据添加上
    NSRange endRange = [aStr rangeOfString:@"\r"];
    if (endRange.location != NSNotFound) {
        //这里表示数据已经读取完成了
        //在if代码块中处理receiveData
        receiveData = nil;//用于接受数据的对象置空
    }
    //别忘了设置timeout
    [client readDataWithTimeout:-1 tag:0];
}

注意这一行代码

NSRange endRange = [aStr rangeOfString:@"\r"];

服务器在发送socket数据时,在结束的时候一定都会有一个标记,这里我请求的服务器的结束标记就是\r,不同的服务器可能有不同的标记,但往往不外乎\r、\0、\n之类的,可以自己尝试一下。
endRange表示\r的出现位置,如果\r出现了,就表示数据已经完成读取,可以处理了,如果\r不出现,didReadData函数会一直执行,知道数据完全被获取到。

此外,除了结束符标记法之外,我们还可以根据content-length来判断。第一次获取数据,即使不完整,但是返回报文头的content-length还是可以获取到的,以后以后每次获取数据,就判断长度是否已经达到。不过这种方法需要找到返回的数据内容并计算data长度,比较繁琐,可以作为备用方法,这里就不实现了。

至于服务器端,也存在这样的问题。不过服务器端的设置比较简单。didReadData的修改类似于客户端。至于timeout,我们可以不在didReadData方法中设置,因为这样的设置会导致第一次总是会拿到数据。我们可以放在didReadData函数被调用之前就设置。如:

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ 
    //…………
    //前面是各种处理
    [sock readDataWithTimeout:-1 tag:0];
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值