Чтение данных из CocoaAsyncSocket

Я использую CocoaAsyncSocket , мне нужно создать функцию, которая отправляет сообщение на сервер и ждет, пока сервер ответит, в методах делегата он получает ответ сервера, но мне нужна функция, которая отправляет сообщение, ждет ответа сервера и вернуть ответ.

- (NSString *)sendMessage:(NSString *)message{
    NSError *err = nil;
    if (![socket connectToHost:@"192.168.1.20" onPort:52523 error:&err]) // Asynchronous!
    {
        NSLog(@"Error is : %@", err);
    }

   [socket readDataWithTimeout:-1 tag:1];

    NSData* data =[message dataUsingEncoding:NSUTF8StringEncoding];
    [socket writeData:data withTimeout:-1 tag:1];

    NSString *xmlString = [[NSString alloc] init];
    // Here I need the function wait and receive the response

    return xmlString;
}

person Raheel Sadiq    schedule 10.11.2012    source источник


Ответы (1)


Если вам нужно отправить что-то синхронно, почему бы не создать запрос и не использовать API NSURLConnection, как здесь:

NSData* data = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];   

Это заблокирует, пока вы не получите ответ.

Если вы хотите продолжать использовать подход с асинхронным сокетом, но принудительно сделать его синхронным вызовом, вы можете сделать это, добавив следующие методы:

@property (nonatomic, assign) BOOL com_private_condition;
@property (nonatomic, assign) NSThread* com_private_theWaitingThread;

...

@synthesize com_private_condition;
@synthesize com_private_theWaitingThread;

...

    - (BOOL)waitForConditionWithTimeout:(NSTimeInterval)aTimeout
    {
        self.com_private_condition = NO;
        self.com_private_theWaitingThread = [NSThread currentThread];
        NSDate* theStartDate = [NSDate date];
        NSDate* theEndDate = [NSDate dateWithTimeIntervalSinceNow:aTimeout];
        do 
        {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                                 beforeDate:theEndDate];
        NSTimeInterval theElapsedTime = -[theStartDate timeIntervalSinceNow];
        if (theElapsedTime >= aTimeout)
        {
            return NO;
        }
        if (self.com_private_condition)
        {
            return YES;
        }
    } while (YES);
}

- (void)signalCondition
{
    [self performSelector:@selector(com_private_signalCondition:) 
                 onThread:self.com_private_theWaitingThread 
               withObject:nil waitUntilDone:NO];
}

- (void)com_private_signalCondition:(id)aParam
{
    self.com_private_condition = YES;    
}

Теперь сделайте свой метод таким

- (NSString *)sendMessage:(NSString *)message{
    NSError *err = nil;
    if (![socket connectToHost:@"192.168.1.20" onPort:52523 error:&err]) // Asynchronous!
    {
        NSLog(@"Error is : %@", err);
    }

   [socket readDataWithTimeout:-1 tag:1];

    NSData* data =[message dataUsingEncoding:NSUTF8StringEncoding];
    [socket writeData:data withTimeout:-1 tag:1];

    //make xmlString a variable on your class and set it in your async socket callback when you get the data. once the wait is over just return it.
    //NSString *xmlString = [[NSString alloc] init];
    // Here I need the function wait and receive the response

    //call read and then wait
    [socket readDataWithTimeout:-1 tag:1];
    [self waitForConditionWithTimeout:9999.0]; //or some other wait timeout of your choosing
    //this will block until [self signalCondition] is called by your socket callbacks.

    return self.xmlString;
}

Теперь в вашем сокете обратного вызова CocoaAsyncSocket: didReadData: withTag: и socket: didDisconnectWithError: убедитесь, что вы вызываете

[self signalCondition];

Как только вы вызовете этот метод, ожидание будет продолжено, и вы только что сделали асинхронный вызов синхронным.

person foggzilla    schedule 10.11.2012
comment
Я очень ценю то, как вы кратко ответили, предоставленное вами решение действительно работоспособно, я делаю это через сокеты, потому что сокеты более эффективны во времени, мой проект должен быть эффективным во времени. Спасибо - person Raheel Sadiq; 10.11.2012