У меня странная проблема при попытке использовать 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
никогда не вызывается и приложение зависает.
Кто-нибудь может сказать мне, что не так?