我在尝试使用AsyncSocket时遇到了一个奇怪的问题。在我的应用程序中,我实际上需要同步套接字,因为我自己在后台处理所有不同级别的通信。因此,我尝试围绕AsyncSocket类SyncSocket编写包装器。这是代码:

// SyncSocket.h
#import <Foundation/Foundation.h>
#import "AsyncSocket.h"

@interface SyncSocket : NSObject <AsyncSocketDelegate> {
    AsyncSocket* _asyncSocket;
    NSTimeInterval _connectTimeout;
    NSTimeInterval _readTimeout;
    NSTimeInterval _writeTimeout;
    BOOL _waiting;
    BOOL _nsLog;
}

@property (nonatomic, assign) BOOL waiting;
@property (nonatomic, assign) BOOL nsLog;

- (id) initWithConnectTimeout: (NSTimeInterval) connectTimeout readTimeout: (NSTimeInterval) readTimeout writeTimeout: (NSTimeInterval) writeTimeout;

- (BOOL) connectToHost: (NSString*) host onPort: (UInt16) port;

@end

// SyncSocket.m
#import "SyncSocket.h"

@implementation SyncSocket
@synthesize waiting = _waiting;
@synthesize nsLog = _nsLog;

//
// Constructor/destructor
//

- (id) initWithConnectTimeout: (NSTimeInterval) connectTimeout readTimeout: (NSTimeInterval) readTimeout writeTimeout: (NSTimeInterval) writeTimeout {
    [super init];
    if (self == nil)
        return self;

    _connectTimeout = connectTimeout;
    _readTimeout = readTimeout;
    _writeTimeout = writeTimeout;
    _waiting = NO;

    _asyncSocket = [[AsyncSocket alloc] initWithDelegate: self];

    return self;
}

- (void) dealloc {
    [_asyncSocket release];
    [super dealloc];
}

- (BOOL) connectToHost: (NSString*) host onPort: (UInt16) port {
    if (self.nsLog)
        NSLog (@"connectToHost: %@ onPort: %d", host, port);

    _waiting = YES;
    NSError* err = nil;
    if (![_asyncSocket connectToHost: host
                      onPort: port
                     withTimeout: _connectTimeout
                   error: &err])
        return NO;

    while (self.waiting && [_asyncSocket isConnected] == NO) {
        [NSThread sleepForTimeInterval: 0.01];
    }


    return [_asyncSocket isConnected];
}

- (void) writeData: (NSData*) data {
    _waiting = YES;
    [_asyncSocket writeData: data withTimeout: _writeTimeout tag: 0];

    while (self.waiting) {
        [NSThread sleepForTimeInterval: 0.01];
    }
}


//
// AsyncSocket delegates
//
- (BOOL)onSocketWillConnect:(AsyncSocket *)sock {
    if (self.nsLog)
        NSLog (@"onSocketWillConnect:");
    return YES;
}

- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag {
    if (self.nsLog)
        NSLog (@"didWriteDataWithTag: %d", tag);
    _waiting = NO;
}

- (void) onSocket: (AsyncSocket*) sock willDisconnectWithError: (NSError*) err {
    if (self.nsLog)
        NSLog (@"willDisconnectWithError: %d", [err code]);

    _waiting = NO;
}

- (void) onSocket: (AsyncSocket*) sock didConnectToHost: (NSString*) host port: (UInt16) port {
    if (self.nsLog)
        NSLog (@"didConnectToHost: %@ port: %d", host, port);

    _waiting = NO;
}

@end


问题是:AsyncSocket可以很好地连接到主机,但是永远不会调用我的委托didConnetToHost。而且,如果我调试AsyncSocket代码,即使设置了respondsToSelector,我也可以看到失败。看起来好像有一些奇怪的内存冲突之类的东西,但是我不知道我在哪里犯了错误。

有任何想法吗?关于如何将AsyncSocket封装为同步套接字,有一个很好的例子吗?

PS:只需清楚一点:XCode 3.2.5,iPhone Simulator 4.2。

更新:之所以尝试用SyncSocket包装它,是因为我想从应用程序的业务逻辑中隐藏所有套接字委托的内容。我需要在许多不同的地方使用套接字连接,并且我不想在许多不同的地方实现底层的套接字功能(例如检测套接字的状态,接收消息的标头,然后是正文等)。我想要一个简单的界面,在其中我可以打开/发送/接收并且不必担心底层实现。我确实知道网络连接应该在单独的线程中运行,这很好-在主线程中委派一名后台工作人员不是问题。

因此,我以AsyncSocket存储库中的InterfaceTest示例为起点。从那里删除了DNS相关的内容。工作良好。 didConnect被调用,一切都闪闪发亮。

然后,我将SyncSocket实现添加到项目中,以查看问题所在。可以在这里下载项目:http://dl.dropbox.com/u/6402890/NetworkTest.zip-可能有人可以告诉我我做错了什么-我感到我在SyncSocket中没有正确使用线程。

如果我在等待循环中同时使用asyncSocket is Connected和内部的self.waiting-它会退出该循环并调用didConnect(但在循环结束后)。如果我尝试仅使用在didConnect中设置的self.waiting-永不调用didConnect且应用程序挂起。

谁能告诉我怎么了?

最佳答案

发现问题。看起来我不得不从更改使用的等待循环:

[[NSThread sleepForTimeInterval: 0.01]


要使用RunLoop:

[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];

10-08 12:25