我試圖使用GCDAsyncSocket向我的iDevice客戶端發送一些圖像文件(幾乎100MB)。我想同步發送數據包到客戶端。我的意思是在發送100MB數據給第一個客戶端迭代到下一個客戶端之後。但是因爲異步性質GCDAsyncSocket我不知道如何序列化這些包發送。同步Objective-C中的異步任務
我無法使用信號量,因爲在發送圖像之前,我會與每個客戶端協商以瞭解應發送的圖像,然後嘗試發送這些圖像。我找不到一個乾淨的方式來等待和發出信號。
- (void)sendImagesToTheClients:clients
{
...
//negotiating with client to know which images should sent
...
for(Client* client in clients)
{
packet = [packet addImages: images];
[self sendPacket:packet toClient:client];
}
}
- (void)sendPacket:packet toClient:client
{
// Initialize Buffer
NSMutableData *buffer = [[NSMutableData alloc] init];
NSData *bufferData = [NSKeyedArchiver archivedDataWithRootObject:packet];
uint64_t headerLength = [bufferData length];
[buffer appendBytes:&headerLength length:sizeof(uint64_t)];
[buffer appendBytes:[bufferData bytes] length:[bufferData length]];
// Write Buffer
[client.socket writeData:buffer withTimeout:-1.0 tag:0];
}
這是AsyncSocket寫入數據是如何工作的:
- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
{
if ([data length] == 0) return;
GCDAsyncWritePacket *packet = [[GCDAsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];
dispatch_async(socketQueue, ^{ @autoreleasepool {
LogTrace();
if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
{
[writeQueue addObject:packet];
[self maybeDequeueWrite];
}
}});
// Do not rely on the block being run in order to release the packet,
// as the queue might get released without the block completing.
}
所以沒有任何人有任何想法我怎麼能同步這個任務?
UPDATE
的套接字連接我用GCDAsyncSocket一個大量使用代表團事件通知。(GCDAsyncSocket.h和GCDAsyncSocket.m)(與completionHandler沒有方法)。
我寫了一個名爲TCPClient的類,它處理套接字連接和數據包發送,並將其設置爲初始化套接字的委託。 寫入數據包後,代理方法- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
被調用。它只會通知我一些數據已經寫入。在這裏我不能根據書面數據來決定撥打dispatch_group_leave
。所以依靠委託方法是沒用的。
我已經修改[client.socket寫數據:緩衝withTimeout:-1.0標籤:0] GCDAsyncSocket.h和.m文件接受completionBlock:使用這種方法[client.socket writeData:buffer withTimeout:-1.0 tag:0 completionBlock:completionBlock]
幫助我解決同步異步任務。
// perform your async task
dispatch_async(self.socketQueue, ^{
[self sendPacket:packet toClient:client withCompletion:^(BOOL finished, NSError *error)
{
if (finished) {
NSLog(@"images file sending finished");
//leave the group when you're done
dispatch_group_leave(group);
}
else if (!finished && error)
{
NSLog(@"images file sending FAILED");
}
}];
但問題是更新GCDAsyncsocket後,我的代碼可能會中斷。 這裏我正在尋找整潔的方式來添加完成處理程序到GCDAsyncsocket而不直接修改它。比如創建一個包裝器或使用Objective-C運行時的特性。 你有什麼想法嗎?
' - (無效)寫數據:(NSData的*)數據withTimeout:(NSTimeInterval)超時標記: (long)tag'是'GCDAyncSocket.m'中的一個方法,我不應該修改它。我可以將我的socketQueue傳遞給'GCDAsynSocket'。我應該創建另一個dispatch_async並將'sendPacket:client:'放在它中,然後調用'dispatch_group_leave(group);'?因爲我做了但沒有改變。仍然是異步的。 – 2014-10-29 05:57:35
'GCDAsyncSocket'通過委託調用通知我完成通過'didWriteDataWithTag:'問題是在這裏這個方法不會發送寫入的數據到基於這些數據(如果它們是圖像)我稱之爲'dispatch_group_leave(group);'。 GCDAsyncSocket不通過completionHandler通知我。 – 2014-10-29 06:29:05
請更新您的問題以反映此庫的委託性質。我會更新我的答案,你可以把'dispatch_group_leave'放在委託方法中,它應該仍然可以工作。 – thelaws 2014-10-29 15:50:34