Хорошо, получается, что ответ был на самом деле довольно простым. Вы можете использовать:
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
}
}
}
Итак, важные вещи, которые нужно осознать, были:
Нет необходимости привязывать что-либо к сокету, который вы слушаете; вместо этого можно произвольно связать экземпляры CFReadStream
и CFWriteStream
с любым уже подключенным сокетом, даже если вы уже читали / записывали данные из / в него.
При всей своей причудливой многословности, CFSocketNativeHandle
- это просто int
. О, как я ненавижу ненужное наложение примитивных типов на вещи, которые звучат так, как будто они не примитивные типы.