Не удается записать в CFWriteStream, успешно созданный с помощью CFStreamCreatePairWithSocket - PullRequest
1 голос
/ 05 марта 2012

Я сталкиваюсь с проблемой, когда пытаюсь установить двунаправленную асинхронную связь благодаря CFWrite / ReadStream в среде разработки iOS.

Я начинаю создавать сокетное соединение, и все кажется правильным:

CFSocketContext socketCtx = {0, self, NULL, NULL, NULL};
socket = CFSocketCreate(NULL, PF_INET, SOCK_STREAM, IPPROTO_TCP,kCFSocketConnectCallBack, (CFSocketCallBack)onConnectOrDisconnect, &socketCtx);

CFSocketEnableCallBacks(socket, kCFSocketConnectCallBack);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(appDelegate.portSocket);
addr.sin_addr.s_addr = inet_addr([adress cStringUsingEncoding:NSASCIIStringEncoding]);
CFDataRef connectAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));   
CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes);
CFRelease(sourceRef);
CFSocketConnectToAddress(socket, connectAddr, -1);

Затем в своем обратном вызове соединения я создаю два потока, один для чтения, другой для записи:

void onConnectOrDisconnect(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address,
                           const void *data, void *info)
{
    TCPClient * clientTCP = (TCPClient *)info;
    if(data==NULL)
    {
        [clientTCP ConnectionSuccess];
    }else {
        SInt32 *error = (SInt32*)data;
        NSLog(@"Connection error : %d", *error);
        StreamErrorOccured(clientTCP);
    }
}
- (void) ConnectionSuccess
{
    CFStreamCreatePairWithSocket(kCFAllocatorDefault, CFSocketGetNative(socket), &readStream, &writeStream);
    CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
    CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
    CFStreamClientContext dataStreamContext = {0, self, NULL, NULL, NULL};  
    CFOptionFlags events = kCFStreamEventHasBytesAvailable | kCFStreamEventOpenCompleted;
    if (CFReadStreamSetClient(readStream, events, readStreamEventCallBack , &dataStreamContext)) 
    {
        CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
    }
    if (CFWriteStreamSetClient(writeStream, kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
                               writeStreamEventCallBack, &dataStreamContext))
    {
        CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
    }else {
        NSLog(@"can't create write stream client");
    }

    CFReadStreamOpen(readStream);
    CFWriteStreamOpen(writeStream);

    NSLog(@"Connection Success");
}

Обратите внимание, что я зарегистрировал обратный вызов для событий kCFStreamEventCanAcceptBytes и kCFStreamEventOpenCompleted.В этом обратном вызове я вижу, что kCFStreamEventOpenCompleted произошел, но kCFStreamEventCanAcceptBytes никогда не происходит!

Когда я пытаюсь записать в свой поток, я проверяю доступность потока благодаря: CFWriteStreamCanAcceptBytes (writeStream).Эта функция всегда возвращает false.

Если я попытаюсь записать поток без вызова CFWriteStreamCanAcceptBytes, цикл операции записи будет длиться вечно.Мои вопросы: 1. Почему я не получаю никакого события kCFStreamEventCanAcceptBytes?2. Почему я не могу писать в своем потоке?

Я видел, что моя проблема точно такая же, как: ПОХОЖИЕ ВОПРОС но никто не отвечает ему.

Может быть, я будуеще повезет!

Ура,

1 Ответ

0 голосов
/ 04 марта 2015

Я не знаю ответа, но я тоже столкнулся с этой проблемой.Решением является получение события «kCFStreamEventCanAcceptBytes» в вашем writeStreamEventCallBack и запись данных в эту функцию обратного вызова.На самом деле проблема в том, что если вы не отправили данные о событии 'kCFStreamEventCanAcceptBytes', вы не сможете отправить данные в следующий раз.

Страница документации Apple dev гласит:

Когда вы используете API CFStream для работы в сети, операции чтения и записи на сокетах могут блокироваться.Чтобы предотвратить блокировку:

  1. Вызовите CFReadStreamSetClient и CFWriteStreamSetClient, чтобы зарегистрироваться для получения уведомлений о событиях, связанных с потоком.

  2. Вызовите CFReadStreamScheduleWithRunLoop и CFWriteStreamScheduleWithRunLove по расписаниюв цикле выполнения для получения уведомлений о событиях, связанных с потоком.

  3. Вызовите CFReadStreamOpen и CFWriteStreamOpen, чтобы открыть каждый поток.

  4. Только чтение после полученияkCFStreamEventHasBytesAvailable уведомление.Запись только после получения уведомления kCFStreamEventCanAcceptBytes.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...