У меня есть странная проблема, пытающаяся использовать 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, заключается в том, что я хотел скрыть все делегированные элементы сокета из бизнес-логики приложения. Мне нужно использовать соединение сокетов во многих разных местах, и я не хочу реализовывать функции сокетов на низком уровне (например, обнаружение состояния сокета, получение заголовка сообщения, затем тело и т. Д.) Во многих разных местах. Я хочу иметь простой интерфейс, где я могу открывать/отправлять/получать и не беспокоиться о реализации на низком уровне. Я понимаю, что сетевое подключение должно выполняться в отдельном потоке, и это прекрасно - сделать одного фонового рабочего в основном потоке не представляет проблемы.
Таким образом, я взял образец InterfaceTest из репозитория AsyncSocket в качестве отправной точки. Оттуда удалены связанные с DNS материалы. Работает отлично. didConnect вызывается, все блестяще.
Затем я добавил проект в реализацию SyncSocket, чтобы узнать, что с ним не так. Проект можно скачать здесь: http://dl.dropbox.com/u/6402890/NetworkTest.zip - может быть, кто-то может сказать мне, что я делаю неправильно - у меня такое ощущение, что я не использую нити правильно в SyncSocket.
Если я использую в ожидании цикла как asyncSocket is Connected
и мой внутренний self.waiting
- она выйдет из этого цикла и didConnect
называется (но после цикла завершен). Если я пытаюсь использовать только мой self.waiting
, который установлен в didConnect - didConnect
никогда не звонил и приложение зависает.
Кто-нибудь может сказать мне, что случилось?
Это не имеет никакого значения. Странная вещь - после вызова метода connect - onSocketWillConnect вызывается, а затем ничего. Я выхожу из цикла, потому что isConnected становится TRUE. – sha
изменить свой метод init: if (self = [super init]) {/ * initialization * /} return self; – Felix
Пробовал. Ничего не изменит. Это эквивалентно тому, что я имел, насколько я понимаю. – sha