我试图获得一个使用 GCDAsyncSocket 的简单示例,并且发现我缺少某些理解,希望各位好人能帮助解释这一点。
我在下面设置了 GCDAsyncSocket 的东西:
dispatch_queue_t mainQueue = dispatch_get_main_queue();
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];
NSString *host = @"192.168.169.132";
uint16_t port = 2112;
DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port);
self.viewController.label.text = @"Connecting...";
NSError *error = nil;
if (![asyncSocket connectToHost:host onPort:port withTimeout:5.0 error:&error])
{
DDLogError(@"Error connecting: %@", error);
self.viewController.label.text = @"Oops";
}
else
{
DDLogVerbose(@"Connecting...");
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
DDLogInfo(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port);
self.viewController.label.text = @"Connected";
// We're just going to send a test string to the server.
NSString *myStr = @"testing...123...\r\n";
NSData *myData = [myStr dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:myData withTimeout:5.0 tag:0];
}
并且可以看到我的套接字测试服务器应用程序接收到字符串
“正在测试...123...\r\n”
但是当我让我的套接字测试服务器发回一个字符串时,我天真地期望didReadData委托执行
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
然而冷酷的现实迫使我学会了这一点,直到我打电话
[asyncSocket readDataWithTimeout:5.0 tag:0];
... didReadData委托不会被调用。
好没问题。我得到它。
更多地阅读文档,它清楚地表明
AsyncSocket 是一个基于 RunLoop 的 TCP 套接字库。
所以现在我在看这个RunLoop的东西,在我看来它就像Microsoft Windows 中的 Message 循环。由于 iOS 是一个事件/msg 驱动的架构(就像 Win32 一样),那么我目前所在的默认主线程显然有它自己的 msg 循环来处理事件。
我的困惑现在让 iOS RunLoop 看起来像是一个单独的实体,必须使用才能让 GCDAsyncSocket 正常工作。
当它声明其默认的运行循环模式集是 NSDefaultRunLoopMode 时,它位于主线程中。
迷茫了吗?
所以在 Win32 下,我的 comm 事件处理代码如下所示:
while( sCOMport.hCOMport != INVALID_HANDLE_VALUE ) // ...while the COM port is open...
{
// Wait for an event to occur on the port.
WaitCommEvent( sCOMport.hCOMport, &dwCommStatus, NULL );
它当然会在它自己的线程中(还没有使用 GCDAsyncSocket 到达那里),但这在某种程度上是它自己的“RunLoop”。
我如何使用GCDAsyncSocket做同样的事情,这样我就不会陷入使用[asyncSocket readDataWithTimeout]调用填充队列的一些轮询循环中?
我觉得我们需要更好的例子来使用这个库。