iOS - Получение CFReadStream / CFWriteStream из сокета - PullRequest
2 голосов
/ 28 марта 2012

Я пытаюсь добавить некоторые простые функции однорангового соединения в библиотеку iOS. Кодирование исходящих соединений было достаточно простым; вызов CFStreamCreatePairWithSocketToHost подключается к удаленному хосту и устанавливает потоки для чтения / записи с / на него. Достаточно просто.

Однако я не смог найти столь же простой способ настроить сокет для прослушивания / приема входящих соединений. Итак, я вернулся к основам и использовал socket(), bind(), listen() и accept() для реализации низкоуровневой обработки соединений, в основном по образцу, приведенному здесь:

http://www.pcs.cnu.edu/~dgame/sockets/server.c

Все хорошо, но теперь, когда я могу принимать входящие соединения, мне интересно, как создать экземпляры CFReadStream и CFWriteStream для управления ими. Есть ли прямой способ сделать это?

Кроме того, я знаю, что существует библиотека CocoaAsyncSocket, которая поддерживает асинхронные серверные сокеты, но я действительно не заинтересован в асинхронном решении.

1 Ответ

8 голосов
/ 29 марта 2012

Хорошо, получается, что ответ был на самом деле довольно простым. Вы можете использовать:

void CFStreamCreatePairWithSocket (
    CFAllocatorRef alloc,
    CFSocketNativeHandle sock,
    CFReadStreamRef *readStream,
    CFWriteStreamRef *writeStream
);

... для привязки CFReadStream и CFWriteStream к уже подключенному гнезду. Этот поток кажется мне немного задом наперед (то есть, что, если байты уже были прочитаны из сокета и т. Д., И почему невозможно просто привязать что-либо к сокету прослушивания / сервера так, чтобы каждый раз принималось новое соединение соответствующие экземпляры CFReadStream и CFWriteStream автоматически настраиваются?), но что угодно.

Код выглядит так:

int connectedSocketId = accept(socketId, (struct sockaddr *)&clientSocket, &addrlen);
if (connectedSocketId != -1) {
    //successful connection
    CFReadStreamRef clientInput = NULL;
    CFWriteStreamRef clientOutput = NULL;
    CFStreamCreatePairWithSocket(kCFAllocatorDefault, connectedSocketId, &clientInput, &clientOutput);

    if (clientInput && clientOutput) {
        CFReadStreamSetProperty(clientInput, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        CFWriteStreamSetProperty(clientOutput, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        if (! CFReadStreamOpen(clientInput) || ! CFWriteStreamOpen(clientOutput)) {
            NSLog(@"Could not initialize streams!");
        }
        else {
            //use the streams
        }
    }
}

Итак, важные вещи, которые нужно осознать, были:

  1. Нет необходимости привязывать что-либо к сокету, который вы слушаете; вместо этого можно произвольно связать экземпляры CFReadStream и CFWriteStream с любым уже подключенным сокетом, даже если вы уже читали / записывали данные из / в него.

  2. При всей своей причудливой многословности, CFSocketNativeHandle - это просто int. О, как я ненавижу ненужное наложение примитивных типов на вещи, которые звучат так, как будто они не примитивные типы.

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