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

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

По сути, я хочу отправить 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 и т. Д.

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

т.е.

sendString
getSendStringResponse

Я немного озадачен тем, как справиться с этим.

Прошу прощения, если мне неясно,

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

1 ответ

Решение

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

Другие вопросы по тегам