2010-07-01 96 views
2

我一直在为使用套接字与另一个应用程序进行通信的iPad应用程序工作,并且在将数据发送到我的服务器应用程序时遇到很多问题。如何实现套接字超时?

我有3个命令,我发送到服务器取决于我需要什么类型的信息,其中一个命令总是发送一个响应,但其他2个不需要,所以我需要在我的应用程序超时知道服务器何时不发送响应。

当我创建套接字时,我注册了一个数据到达时调用的回调函数,这个回调函数应该在后台监听,但我注意到如果我发送数据并暂停应用程序的主线程(暂停它有一段时间或具有睡眠功能)回调从未被调用。

因为我不能在主线程中等待,所以我决定创建一个单独的线程,在这个线程中我所做的就是睡眠线程一段时间(超时),然后检查一个只在回调方法被调用时才设置的标志(换句话说,如果服务器发送响应),并且如果没有设置此标志,那么我知道对服务器超时的请求,并且我可以向前移动。现在

,问题是,我有送50请求到服务器的方法,逻辑是这样:

  1. 方法1发送请求,并开始等待的线程(查询超时)

  2. 等待线程睡眠n秒

  3. 一个 - 如果数据到达,而等待的线程是睡眠,回调方法被调用时,设置一个标志,表明数据已经到达,做一些东西,并调用方法1,循环STA室温超过

    b - 如果为数据数据没有到达,到达的数据标志保持假

  4. 等待线程醒来,检查到达的数据标志

    一个 - 如果该标志为真(数据到达时),退出线程

    b - 如果为标志是假的(数据未到达),调用方法1,并退出线程

但在T工作他的方式是向我的应用程序引入许多问题,行为不正确,并且有时会混淆调用,并且我可以在调试时看到延迟线程连续多次调用,但应该只调用一次每个周期(你可以想象一个周期从1到4,见上面),所以我的猜测是我的问题的原因是我实现我的超时的方式,因为如果我尝试使用命令总是发送回复,我没有任何问题。

有没有人可以帮助我更好地实现等待超时?

谢谢。

回答

2

今天我不得不再次面对这个问题,我来到这个post;这是我打算用来解决上述问题的方法,但由于某种原因,while循环从未在我的应用程序中结束,即使时间间隔已耗尽。

所以我一直在阅读,并且我注意到在帖子中提到的其中一个答案提到了运行循环的观察者,现在,这对我没有多大帮助,但在阅读关于观察者时遇到了timers。因此,基本上我所做的是,因为我的运行循环在耗尽所有时间后永不终止,所以我在运行循环中添加了一个计时器,当计时器到期时,它使用选择器调用一个方法,并且该方法设置超时标志的值和正如帖子的答案之一所解释的那样,因为我正在使用选择器,当我更改标志变量的值时,运行循环立即注意到它,并退出while。

这种方法的好处是应用程序不会被阻塞,因此正在监听服务器数据到达的回调可以完成这项工作。

这里是我使用的代码:

- (IBAction)someRandomAction:(id)sender 
{ 
    Byte byteData[3];  
    int len = 3; 
    byteData[0] = 0; 
    byteData[1] = 0; 
    byteData[2] = 0; 
    CFDataRef refData = CFDataCreate(kCFAllocatorDefault, byteData, len); 
    timeOut = socketsLibrary.dataArribal = NO; 
    [socketsLibrary sendMessage:refData withTag:0]; 

    NSDate* futureDate = [NSDate dateWithTimeIntervalSinceNow:5.0];  
    NSTimer* myTimer = [[NSTimer alloc] initWithFireDate:futureDate       
               interval:0.1       
                target:self       
               selector:@selector(wakeUpMainThreadRunloop:)       
               userInfo:nil       
               repeats:NO]; 
    [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode]; 

    while (!timeOut && !socketsLibrary.dataArribal && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:futureDate]){} 

// do something with the data you expect to receive 

} 

- (void) wakeUpMainThreadRunloop:(id)arg 
{ 
    // This method is executed on main thread! 
    // By having it run will 
    // make sure the main thread stops running the runloop 
    timeOut = YES; 
}

在该代码中,“dataArribal”标志是socketsLibrary内,当数据从远程主机到达,并且回调被调用时,它也调用一个方法使用选择器,并在该方法中,我做:

dataArribal = YES; 

所以当数据已被处理此标志将使运行循环完成。