Почему GCDAsyncSocket readData предназначен для чтения только один раз?

Одна вещь, которую я нашел неинтуитивной в обратном вызове didReadData GCDAsyncSocket, заключается в том, что он не вызывается снова, пока вы не выдадите другой readData. Почему он разработан таким образом? Правильно ли ожидать, что пользователь библиотеки инициирует другой вызов чтения, чтобы получить обратный вызов, или это недостаток дизайна?

e.g.

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
     ...
    // initiate the first read
    self.socket = newSocket;
    [self.socket readDataWithTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    // do what you need with the data...

    // read again, or didReadData won't get called!
    [self.socket readDataWithTimeout:-1 tag:0];
}

person Boon    schedule 05.02.2013    source источник


Ответы (3)


Почему он разработан таким образом?

Пока вы используете только readDataWithTimeout:tag:, может показаться более интуитивным просто вызывать метод делегата всякий раз, когда поступают новые данные.

Но readDataWithTimeout:tag: — не единственный способ чтения данных с помощью GCDAsyncSocket. Есть также, например. readDataToLength:withTimeout:tag: и readDataToData:withTimeout:tag:

Оба этих метода вызывают делегата в определенных точках входящих данных, и вы можете захотеть вызывать разные методы в разных точках обработки.

Например, если вы обрабатывали формат потока, в котором заголовок с разделителями CRLF сопровождался телом переменной длины, длина которого была указана в заголовке, вам может понадобиться чередовать вызовы readDataToData:withTimeout:tag:, чтобы прочитать заголовок, разделитель которого вам известен, а затем readDataToLength:withTimeout:tag:, чтобы прочитать тело, длину которого вы извлекли из заголовка.

person Simon Jenkins    schedule 25.03.2013

Это верно; ожидается, что вы продолжите цикл чтения в методе делегата.

person Community    schedule 25.03.2013

Расширяя слова Саймона Дженкинса:

    - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
    {

        // This method is executed on the socketQueue (not the main thread)
        switch (tag) {
            case CHECK_STAUTS:
                [sock readDataToData:[GCDAsyncSocket ZeroData] withTimeout:READ_TIMEOUT tag:CHECK_STAUTS];
                break;

            default:
                break;
        }


    }



    - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        // This method is executed on the socketQueue (not the main thread)
     dispatch_async(dispatch_get_main_queue(), ^{
            @autoreleasepool {

                if (tag == CHECK_STAUTS) {
    //TODO: parse the msg to find the length.
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

                    [serverSocket readDataToLength:LENGTH_BODY withTimeout:-1 tag:CHECK_STAUTS_BODY]; 

                } else if (tag == CHECK_STAUTS_BODY) {
//TODO: parse the msg to the body content
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
                }

            }
        });


        // Echo message back to client
        //[sock writeData:data withTimeout:-1 tag:ECHO_MSG];
    }
person Gamma-Point    schedule 10.10.2013