私は、AsyncSocketを使用しようとすると奇妙な問題が発生します。私のアプリでは、実際には同期ソケットが必要です。なぜなら、バックグラウンドですべての通信を別のレベルで処理するからです。だから私は、AsyncSocketクラスのSyncSocketの周りにラッパーを書き込もうとしています。AsyncSocketが代理人を呼び出さない
// 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でそれをラップしようとしているのは、アプリケーションのビジネスロジックからすべてのソケットデリゲートを隠すためです。私は多くの異なる場所でソケット接続を使用する必要があり、私は多くの異なる場所で低レベルのソケット関数(ソケットの状態の検出、メッセージのヘッダーの受信など)を実装したくありません。私はオープン/送信/受信が可能で、低レベルの実装について心配しないシンプルなインターフェースを持ちたいと思っています。私は、ネットワーク接続を別のスレッドで実行する必要があることを理解しています。これはうまくいきます。メインスレッドの1人のバックグラウンドワーカーは問題ではありません。
私は出発点としてAsyncSocketリポジトリからInterfaceTestサンプルを取得しました。そこからDNS関連のものが削除されました。正常に動作します。 didConnectが呼び出され、すべてが光っています。
次に私のSyncSocket実装にプロジェクトを追加して、何が問題なのかを確認しました。プロジェクトはここからダウンロードできます:http://dl.dropbox.com/u/6402890/NetworkTest.zip - 誰かが私が間違っていることを教えてくれるかもしれません - 私はSyncSocketでスレッドを正しく使用していないと感じています。
私が待機ループで使用する場合、asyncSocket is Connected
と私の内部self.waiting
- それはそのループから抜け出し、が呼び出されます(しかし、ループが終了した後)。 didConnectで設定されているself.waiting
だけを使用しようとすると、didConnect
が呼び出されず、アプリケーションがハングします。
何が間違っているか教えていただけますか?
任意の違いを確認しなかったこと。不思議なこと - connectメソッドを呼び出した後 - onSocketWillConnectが呼び出されてから何もしません。 isConnectedがTRUEになるので、私はループから脱出しています。 – sha
あなたのinitメソッドを変更する:if(self = [super init]){/ * initialization * /} selfを返す。 – Felix
試しました。何も変更しません。それは私が理解していたものと同等です。 – sha