我试图使用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