0

Я изучаю код примера bonjour/NSStream из лекции № 17 курса Stanford CS193p (программирование iOS) на iTunes U с зимы 2010 года. Пример кода есть here.Как исправить наивную реализацию сервера с помощью CFSocket, чтобы разрешить несколько подключений

В оболочке ореха код образца создает сокет и привязывается к порту 0, так что ему будет предоставлен свободный порт. Затем он публикует службу с этим портом, используя NSNetService (bonjour). NSNetServiceBrowser также запускается при запуске приложения. Доступные услуги размещаются в UITableView. Когда ячейка выбрана, соответствующая услуга разрешена, создается NSOutputStream, и данные могут быть отправлены.

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

- (void) _acceptConnection:(int)fd 
{ 
    int  junk; 

// If we already have a connection, reject this new one. This is one of the 
// big simplifying assumptions in this code. A real server should handle 
// multiple simultaneous connections. 

    if (self.isReceiving) { 
     junk = close(fd); 
     assert(junk == 0); 
    } else { 
     [self _startReceive:fd]; 
    } 
} 


// Called by CFSocket when someone connects to our listening socket. 
// This implementation just bounces the request up to Objective-C. 
static void AcceptCallback(CFSocketRef s, 
          CFSocketCallBackType type, 
          CFDataRef address, 
          const void *data, 
          void *info) 

{ 
    ReceiveServer * obj; 

    assert(type == kCFSocketAcceptCallBack); 

    assert(data != NULL); 

    obj = (ReceiveServer *) info; 
    assert(obj != nil); 

    assert(s == obj->_listeningSocket); 


    [obj _acceptConnection:*(int *)data]; 
} 
+1

Перед тем как ответить на этот вопрос: знаете ли вы, как писать многоклиентский сервер с обычными сокетами BSD на Mac (или Linux, Windows или другой настольной/серверной системой)? Если нет, вам, вероятно, следует сначала это узнать или переключиться на более высокоуровневую структуру, которая позаботится об этом, поэтому вам не нужно его изучать. (CFSocket - это своего рода среда среднего уровня, которая добавляет много поверх сокетов, но недостаточно, чтобы просто подключить логику вашего сервера и иметь сервер.) – abarnert

+0

Эй, абарн. Спасибо за ваш ответ. Я не знаю, как написать многоклиентский сервер с обычными сокетами BSD, но я определенно хочу учиться. Можете ли вы предложить несколько хороших ресурсов или пример кода? Я немного посмотрел на [Beej's Guide to Network Programming] (http://beej.us/guide/bgnet/output/print/bgnet_USLetter.pdf). Будет ли понимание того, что меня туда доставит? Постскриптум это то, что я узнаю в базовом сетевом классе? – RyanM

+0

Только что начал читать Addison Wesley: Unix Сетевое программирование: D – RyanM

ответ

1

Я специально не знаком с этим, конечно, или образец кода, но: отделить код для обработки соединения в другой класс из кода, который принимает новые соединения. Итак, в опубликованном коде вы переместите метод -startReceive: и все, что он вызывает в другом классе.

Затем, каждый раз, когда соединение принимается, создайте экземпляр этого другого класса. Этот экземпляр будет отвечать за обработку всей связи по этому соединению. При инициализации ему будет предоставлена ​​информация о соединении (главным образом, fd). Основной объект контроллера сервера может содержать эти экземпляры в массиве.

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

Смежные вопросы