把玩 GCDAsyncSocket 時,一開始試用了 readDataToData 函數,但發現這東西不是我想要的,也就是 server 沒有吐出預設字元(newline)時,程式端無法處理已接收的資料,但可以得知已經接收多少 Partial Data (可用在回報下載、上傳進度)。爾後用一些關鍵字(partial data)找找,發現也有人有這種需求:Is there a way to get partial data read and clear the buffer?
原來會有這種困惑只是不懂 GCDAsyncSocket 設計架構,搞懂後就一切安好啦。
There are 3 methods of reading data using GCDAsyncSocket / AsyncSocket:
- readDataWithTimeout : reads chunks of data as they arrive
- readDataToLength : read a specific length of data before returning result
- readDataToData : read until finding a specific terminator
對於不能確定 Server 回傳的資料長度或特徵的行為,就適合採用 readDataWithTimeout 方式 :)
- (GCDAsyncSocket*)asyncSocket {
if(!_asyncSocket)
_asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_queue_create("socket", NULL)];
return _asyncSocket;
}
- (NSMutableData *)buffer {
if (!_buffer) {
_buffer = [[NSMutableData alloc] init];
}
return _buffer;
}
- (void)viewDidLoad {
[super viewDidLoad];
if (![self.asyncSocket connectToHost:@"ServerIP" onPort:80 error:&error]) {
NSLog(@"ERROR: %@", error);
}
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
NSLog(@"didConnectToHost");
[sock readDataWithTimeout:-1 buffer:self.buffer bufferOffset:[self.buffer length] tag:1];
}
- (void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag {
NSLog(@"didReadPartialDataOfLength");
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSLog(@"didReadData(%lu): %@", tag, @([data length]));
[self.buffer setLength:0];
[sock readDataWithTimeout:-1 buffer:self.buffer bufferOffset:[self.buffer length] tag:tag];
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
NSLog(@"socketDidDisconnect: %@", err);
}
- (void)socketDidSecure:(GCDAsyncSocket *)sock {
NSLog(@"socketDidSecure");
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
NSLog(@"didWriteDataWithTag");
}
沒有留言:
張貼留言