ch++;
write(fd, &ch, 1);
}
}
}
}
}
}
В реальную программу было бы неплохо вставить переменную, содержащую наибольший подключенный номер fd
(необязательно самый последний подключенный номер fd
). Это помешает просмотру в цикле тысяч номеров fd
, которые даже не подсоединены и потенциально не могут быть готовы к чтению. Мы пропустили этот фрагмент кода для краткости и простоты примера.
При запуске этой версии сервера многочисленные клиенты будут обрабатываться последовательно в единственном процессе.
$ ./server5 &
[1] 26686
server waiting
$ ./client3 & ./client3 & ./client3 & ps x
[2] 26689
[3] 26690
adding client on fd 4
server waiting
[4] 26691
PID TTY STAT TIME COMMAND
26686 pts/1 S 0:00 ./server5
26689 pts/1 S 0:00 ./client3
26690 pts/1 S 0:00 ./client3
26691 pts/1 S 0:00 ./client3
26692 pts/1 R+ 0:00 ps x
$ serving client on fd 4
server waiting
adding client on fd 5
server waiting
adding client on fd 6
char from server = В
serving client on fd 5
server waiting
removing client on fd 4
char from server = В
serving client on fd 6
server waiting
removing client on fd 5
server waiting
char from server = В
removing client on fd 6
server waiting
[2] Done ./client3
[3]- Done ./client3
[4]+ Done ./client3
Для полноты аналогии, упомянутой в начале главы, в табл. 15.5 приведены параллели между соединениями на базе сокетов и телефонными переговорами.
Телефон | Сетевые сокеты |
---|---|
Звонок в компанию по номеру 555-0828 | Подключение к IP-адресу 127.0.0.1 |
Ответ на звонок секретаря приемной | Установка соединения с remote host |
Просьба соединить с финансовым отделом. | Маршрутизация с помощью заданного порта (9734) |
Ответ на звонок администратора финансового отдела | Вызов select вернул управление серверу |
Звонок переадресован свободному менеджеру по работе с корпоративными заказчиками | Сервер вызывает accept , создавая новый сокет на добавочный номер 456 |
Дейтаграммы
В этой главе мы сосредоточились на программировании приложений, поддерживающих связь со своими клиентами с помощью TCP-соединений на базе сокетов. Существуют ситуации, в которых затраты на установку и поддержку соединения с помощью сокетов излишни.
Хорошим примером может служить сервис daytime
, использованный ранее в программе getdate.c. Вы создаете сокет, выполняете соединение, читаете единственный ответ и разрываете соединение. Столько операций для простого получения даты!
Сервис daytime
так же доступен с помощью UDP-соединений, применяющих дейтаграммы. Для того чтобы воспользоваться им, просто пошлите сервису одну дейтаграмму и получите в ответ единственную дейтаграмму, содержащую дату и время. Все просто.
Сервисы, предоставляемые по UDP-протоколу, применяются в тех случаях, когда клиенту нужно создать короткий запрос к серверу, и он ожидает единственный короткий ответ. Если стоимость времени процессора достаточно низкая, сервер способен обеспечить такой сервис, обрабатывая запросы клиентов по одному и разрешая операционной системе хранить очередь входящих запросов. Такой подход упрощает программирование сервера.
Поскольку UDP — не дающий гарантий сервис, вы можете столкнуться с потерей вашей дейтаграммы или ответа сервера. Если данные важны для вас, возможно, придется тщательно программировать ваших UDP-клиентов, проверяя ошибки и при необходимости повторяя попытки. На практике в локальных сетях UDP-дейтаграммы очень надежны.