Чтение сложных ответов сокета

У меня есть вопрос о дизайне кода, я не могу придумать наиболее эффективный способ справиться с этим:

По сути, я хочу отправить запрос JSON и прочитать ответ с сервера за один раз.

У меня есть такие методы, как:

-(BOOL)sendString:(NSString *)sendString;
//This should return a NSString and a BOOL
-(NSDictionary *)loginRequestWithEmail:(NSString *)userEmail andPassword:(NSString     *)userPassword;
//This should return a NSString and a BOOL
-(NSDictionary *)requestNewUserAccountWithDisplayName:(NSString *)displayName Email:    (NSString *)userEmail andPassword:(NSString *)userPassword;

Я объясню, что

-(BOOL)sendString:(NSString *)sendString;

делает, в основном отправляет строку JSON на сервер и получает ответ о том, произошел ли сбой или нет.

Я знаю, как записать это на сервер и прочитать это. Проблема заключается в том, чтобы сделать это вместе, поэтому я могу вернуть это значение BOOL как true или false, чтобы увидеть, сработало ли оно.

Теперь после записи в сокет я получаю ответ и должен прочитать его через метод делегата:

-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {

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

Поскольку это происходит, у меня не может быть метода, который делает это:

-(BOOL)sendString:(NSString *)sendString{

NSError *error;

NSLog(@"Sending String: %@",sendString);

NSDictionary *blobData = [NSDictionary dictionaryWithObjectsAndKeys:
                          sendString,@"string",
                          nil];
NSString *blobString = [[NSString alloc]
                        initWithData:[NSJSONSerialization dataWithJSONObject:blobData options:kNilOptions error:&error]
                        encoding:NSUTF8StringEncoding];
NSLog(@"Blob Created: %@", blobString);
NSDictionary *requestData = [NSDictionary dictionaryWithObjectsAndKeys:
                             @"send_string",@"request_type",
                             [NSNumber numberWithInt:0],@"security_level",
                             @"ios",@"device_type",
                             //No Email Provided, This is just for testing
                             blobString,@"blob",
                             nil];

NSData *JSONRequestData = NULL;
JSONRequestData = [NSJSONSerialization dataWithJSONObject:requestData options:kNilOptions error:&error];
        NSLog(@"Contents of JSONRequestData: %@",[[NSString alloc] initWithData:JSONRequestData encoding:NSUTF8StringEncoding]);
JSONRequestData = [[[[NSString alloc] initWithData:JSONRequestData encoding:NSUTF8StringEncoding] stringByAppendingString:@"\\n"] dataUsingEncoding:NSUTF8StringEncoding];
//Write the data
NSMutableData *JSONRequestDataWithLineEnding = [[NSMutableData alloc] initWithData:JSONRequestData];
[JSONRequestDataWithLineEnding appendData:[GCDAsyncSocket CRLFData]];
[asyncSocket writeData:JSONRequestDataWithLineEnding withTimeout:-1 tag:1];

//read a response
[asyncSocket readDataWithTimeout:-1 tag:2];

//This should be done in the didRead delegate
NSString *failure = [serverJSONResponseParsed objectForKey:@"failure"];
NSLog(@"Contents of string failure: %@", failure);

if ([failure isEqualToString:@"none"]) {
    NSLog(@"Success Sending String");
    return TRUE;
}
else {
    NSLog(@"Failure: %@",failure);
    return FALSE;
}

}

Поскольку код, вызываемый после

[asyncSocket readDataWithTimeout:-1 tag:2];

выполняется до того, как данные будут прочитаны (потому что все это асинхронно).

Я понимаю, что должен что-то сделать в этом методе делегата. Это нормально, но мне приходят разные типы ответов, и каждый ответ нужно обрабатывать по-разному.

Моя идея такова: пометить каждую из команд записи, а затем использовать некоторые

if(this_tag) {do this} ....else if(that_tag) {do this} ....

в методе делегата didReadData.

Но как правильно вернуть эти данные? Иногда мне нужно вернуть BOOL, иногда мне нужно вернуть NSDictionary, NSString и т. д.

Я хотел бы, чтобы каждый из моих методов запроса, упомянутых выше, возвращал связанные с ними данные, но я не могу (по крайней мере, неэффективно). Должен ли я делать два разных метода для каждого запроса?

i.e.

sendString
getSendStringResponse

Я немного смущен тем, как справиться с этим.

Я извиняюсь, если я не ясно,

Я ценю любую помощь, которую я могу получить.


person khaliq    schedule 19.08.2012    source источник


Ответы (1)


Что бы я сделал, так это создал протоколы определенного типа для этого конкретного приложения. Например, предположим, что у вас есть следующие типы данных (не связанные с Obj-C): dat1, dat2, dat3 и т. д., которые это приложение должно отправить и получить соответствующий ответ в виде res1, res2, res3 и т. д. с подписью для каждого типа данных для отправляющей части, а также для отвечающей части. Перед отправкой каждых данных вам необходимо префикс данных с подписью. На стороне получателя, используя readDataWithTimeout, в методе обратного вызова didReadData извлеките заголовок для полученных данных и решите ответ на основе протоколов, которые вы согласовали/разработали ранее. Есть и другие дополнительные шаги, прежде чем это будет законченный дизайн. Например, как часть информации вашего заголовка, она может содержать другую информацию, такую ​​как длина данных и т. д. Надеюсь, это поможет вам начать работу.

person user523234    schedule 20.08.2012
comment
Спасибо, это была идея. Я могу использовать теги в методе делегата, чтобы определить, какой ответ какой... таким образом мне не нужно возиться с заголовком. - person khaliq; 20.08.2012
comment
Если вы используете тег, чтобы определить, какой оператор чтения использовать, это не сработает. Это потому, что тег никогда не отправляется вместе с вашими данными получателю. Другими словами, значение тега получателя не совпадает со значением тега отправителя. Если, конечно, вы не отправили его в качестве заголовка. - person user523234; 20.08.2012
comment
О, хорошо, я понимаю, что вы имеете в виду. Если сервер не предназначен для обработки заголовков, то я не могу использовать эту опцию, верно? - person khaliq; 20.08.2012
comment
Не обращайте внимания на последнее предложение моего последнего комментария. Возможно, это привело вас в замешательство. По сути, нет никакой связи между значением тега на стороне отправителя и получателя. Помните: GCDAsyncSocket — это связь через сокет относительно низкого уровня. Вам нужно будет самостоятельно придумать протоколы связи на уровне приложений. - person user523234; 22.08.2012
comment
Да, я понимаю. Вот о чем я думал. Я ценю вашу помощь! - person khaliq; 22.08.2012