Почему библиотечные (делегированные) методы не вызываются? CocoaAsyncSocket

Я застрял в этой проблеме в течение нескольких дней и, похоже, все ближе к решению (с помощью великих пользователей @ SO). Я использую библиотеку CocoaAsyncSocket для создания TCP-сокета с сервером Windows.

Соединение устанавливается в моем appDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    socket = [[AsyncSocket alloc] initWithDelegate:self];
    NSError *error = nil;
    if (![socket connectToHost:@"199.5.83.63" onPort:11005 error:&error]) 
    {
        NSLog(@"Error connecting: %@", error);
    }

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[tekMatrixViewController alloc] initWithNibName:@"tekMatrixViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

У меня есть метод подключения (часть библиотеки) под названием onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *) порт хоста:(UInt16) порт:

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    NSLog(@"connected :D");
}

Этот метод вызывается, поскольку я вижу вывод из NSLOG, и я успешно подключен. Я также вижу, что соединение успешно с компьютера Windows (с использованием файлов журнала).

Я также проверил, что другой метод делегата также вызывается:

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
    NSLog(@"error - disconnecting");
    // start reconnecting procedure here...
}

Я проверил, что метод willDisconnectWithError работает, запустив мое приложение в симуляторе, а затем отключив шнур Ethernet от моего ноутбука. Как только я сделал это, я увидел в своем выводе строку "ошибка - отключение".

Однако большая проблема заключается в том, что мой метод делегата (опять же из библиотеки) не вызывается.

Метод делегата не вызывается:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length])];
    NSString *msg = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
    if(msg)
    {
        NSLog(@"RX:%@",msg);
    }
    else 
    {
        NSLog(@"Fail");
    }    
}

Я уверен в своих знаниях и понимании того, как работают методы делегатов, но я все еще не совсем понимаю, КАК они ПРИЗНАНЫ. Для дальнейшего усложнения и возникновения путаницы вызывается один метод делегата (onSocket: didConnectToHost port:), а другой (тег onSocket: didReadData:) не вызывается. К сожалению, это только первый шаг моей проблемы, но мне придется решить эту проблему, прежде чем перейти к другой проблеме.

Любая помощь будет принята с благодарностью. Спасибо

1 ответ

Решение

Из файла AsyncSocket.h:

/**
 * Called when a socket has completed reading the requested data into memory.
 * Not called if there is an error.
**/
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;

Мое первое предположение состоит в том, что у вас есть ошибка, и поэтому ваш метод делегата не вызывается. Вы также реализовали метод делегата для обработки ошибок?

/**
 * In the event of an error, the socket is closed.
 * You may call "unreadData" during this call-back to get the last bit of data off the socket.
 * When connecting, this delegate method may be called
 * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:".
**/
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;

ПРИМЕЧАНИЕ. То, что вы можете подключиться без ошибок, не означает, что вы сможете читать без ошибок. Аргумент об ошибке, который вы передаете в connectToHost:onPort:error: не охватывает все условия ошибки.

РЕДАКТИРОВАТЬ: Не могли бы вы разместить часть кода, где вы вызываете один из методов "readData" на сокете? Там может быть что-то, что упускается из виду. Если, например, сообщение "readData" не отправляется в сокет, то это объясняет, почему ваш метод делегата не вызывается.

РЕДАКТИРОВАТЬ: onSocket:didReadData:withTag: метод будет вызываться только после того, как вы вызовете один из следующих методов readData для сокета. Например:

// The readData and writeData methods won't block (they are asynchronous).
// 
// When a read is complete the onSocket:didReadData:withTag: delegate method is called.
// When a write is complete the onSocket:didWriteDataWithTag: delegate method is called.
// 
// You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.)
// If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method
// is called to optionally allow you to extend the timeout.
// Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect".
// 
// The tag is for your convenience.
// You can use it as an array index, step number, state id, pointer, etc.

/**
 * Reads the first available bytes that become available on the socket.
 * 
 * If the timeout value is negative, the read operation will not use a timeout.
**/
- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;

У меня возникла аналогичная проблема с методом didReadData() в моем клиентском приложении, который не вызывался после того, как мое серверное приложение отправило данные набора через [newSocket writeData:welcomData withTimout:-1 tag:1].

Моя проблема была решена после того, как я вставил следующую строку в метод didConnectToHost(). [clientAsyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];

Теперь мой клиентский метод didReadData() вызывается соответствующим образом всякий раз, когда контент отправляется.

Другие вопросы по тегам