3

GCDAsyncSocket の didReadData コールバックについて直感的ではないことがわかったのは、別の readData を発行しない限り、再度呼び出されないことです。なぜこのように設計されているのですか?ライブラリのユーザーがコールバックを取得するために別の読み取り呼び出しを開始することを期待するのは正しいですか、それともこれは設計上の欠陥ですか?

例えば

- (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];
}
4

3 に答える 3

7

なぜそのように設計されているのですか?

readDataWithTimeout:tag:のみを使用している限り、新しいデータが到着するたびにデリゲート メソッドを呼び出す方が直感的に思えるかもしれません。

しかし、 GCDAsyncSocketでデータを読み取る方法はreadDataWithTimeout:tag:だけではありません。readDataToLength:withTimeout:tag:readDataToData:withTimeout: tag: などもあります。

これらのメソッドは両方とも、受信データの特定のポイントでデリゲートを呼び出します。処理のさまざまなポイントで別のメソッドを呼び出したい場合があります。

たとえば、CRLF で区切られたヘッダーの後に可変長の本文が続き、その長さがヘッダーで提供されるストリーム形式を処理している場合、readDataToData:withTimeout:tag:の呼び出しを交互に行って、そのヘッダーを読み取ることができます。知っている区切り文字、次にreadDataToLength:withTimeout:tag:ヘッダーから取得した長さの本文を読み取ります。

于 2013-03-25T22:01:54.330 に答える
1

それは正しいです; デリゲート メソッドで読み取りループを続行する必要があります。

于 2013-03-25T20:21:47.767 に答える
0

Simon Jenkins 氏の発言を拡張すると、次のようになります。

    - (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];
    }
于 2013-10-10T11:39:27.157 に答える