Эндрю Уэзеролл - Компьютерные сети. 5-е издание
- Название:Компьютерные сети. 5-е издание
- Автор:
- Жанр:
- Издательство:Питер
- Год:2011
- ISBN:9785446100682
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Эндрю Уэзеролл - Компьютерные сети. 5-е издание краткое содержание
Компьютерные сети. 5-е издание - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
6.1.4. Пример программирования сокета: файл-сервер для Интернета
Чтобы узнать, как выполняются настоящие вызовы для сокета, рассмотрим программу, демонстрирующую работу клиента и сервера, представленную в листинге 6.1. Имеется примитивный файл-сервер, работающий в Интернете и использующий его клиент.
У программы много ограничений (о которых еще будет сказано), но в принципе данный код, описывающий сервер, может быть скомпилирован и запущен на любой UNIX-системе, подключенной к Интернету. Код, описывающий клиента, может быть запущен с определенными параметрами. Это позволит ему получить любой файл, к которому у сервера есть доступ. Файл отображается на стандартном устройстве вывода, но, разумеется, может быть перенаправлен на диск или какому-либо процессу.
Листинг 6.1.Программы использования сокетов для клиента и сервера
Рассмотрим сперва ту часть программы, которая описывает сервер. Она начинается с включения некоторых стандартных заголовков, последние три из которых содержат основные структуры и определения, связанные с Интернетом. Затем SERVER_PORT определяется как 12345. Значение выбрано случайным образом. Любое число от 1024 до 65535 подойдет с не меньшим успехом, если только оно не используется каким-либо другим процессом; порты с номерами 1023 и ниже зарезервированы для привилегированных пользователей.
В последующих двух строках определяются две необходимые серверу константы. Первая из них задает размер блока данных для передачи файлов (в байтах). Вторая определяет максимальное количество незавершенных соединений, после установки которых новые соединения будут отвергаться.
После объявления локальных переменных начинается сама программа сервера. Вначале она инициализирует структуру данных, которая будет содержать IP-адрес сервера. Эта структура будет связана с серверным сокетом. Вызов memset полностью обнуляет структуру данных. Последующие три присваивания заполняют три поля этой структуры. Последнее из них содержит порт сервера. Функции htonl и htons занимаются преобразованием значений в стандартный формат, что позволяет программе нормально выполняться как на машинах с представлением числовых разрядов little-endian (например, Intel x86), так и с представлением big-endian (например, SPARC). Детали их семантики здесь роли не играют.
После этого сервером создается и проверяется на ошибки (определяется по s < 0) сокет. В окончательной версии программы сообщение об ошибке может быть чуть более понятным. Вызов setsockopt нужен для того, чтобы порт мог использоваться несколько раз, а сервер — бесконечно, обрабатывая запрос за запросом. Теперь IP-адрес привязывается к сокету и выполняется проверка успешного завершения вызова bind. Конечным этапом инициализации является вызов listen, свидетельствующий о готовности сервера к приему входящих вызовов и сообщающий системе о том, что нужно ставить в очередь до QUEUE_SIZE вызовов, пока сервер обрабатывает текущий вызов. При заполнении очереди прибытие новых запросов спокойно игнорируется.
В этом месте начинается основной цикл программы, который никогда не покидается. Его можно остановить только извне. Вызов accept блокирует сервер на то время, пока клиент пытается установить соединение. Если вызов завершается успешно, accept возвращает дескриптор (описатель) сокета, который можно использовать для чтения и записи, аналогично тому, как файловые дескрипторы (описатели) могут применяться для чтения и записи в каналы. Однако, в отличие от однонаправленных каналов, сокеты двунаправлены, поэтому для чтения (и записи) данных из соединения можно использовать sa (принятый сокет). Файловые дескрипторы канала могут использоваться для чтения или записи, но не для того и другого одновременно.
После установления соединения сервер считывает имя файла. Если оно пока недоступно, сервер блокируется, ожидая его. Получив имя файла, сервер открывает файл и входит в цикл, который читает блоки данных из файла и записывает их в сокет. Это продолжается до тех пор, пока не будут скопированы все запрошенные данные. Затем файл закрывается, соединение разрывается и начинается ожидание нового вызова. Данный цикл повторяется бесконечно.
Теперь рассмотрим часть кода, описывающую клиента. Чтобы понять, как работает программа, необходимо вначале разобраться, как она запускается. Если она называется client , ее типичный вызов будет выглядеть так:
client flits.csvu.nl /usr/tom/filename >f
Этот вызов сработает только в том случае, если сервер расположен по адресу flits. cs.vu.nl, файл/usr/tom/filename существует и у сервера есть доступ по чтению для этого файла. Если вызов произведен успешно, файл передается по Интернету и записывается на местоf , после чего клиентская программа заканчивает свою работу. Поскольку серверная программа продолжает работать, клиент может быть запущен снова с новыми запросами на получение файлов.
Клиентская программа начинается с подключения файлов и объявлений. Работа начинается с проверки корректности числа аргументов (argc = 3 означает, что в строке запуска содержалось имя программы и два аргумента). Обратите внимание на то, чтоargv[1] содержит имя сервера (например, flits.cs.vu.nl) и переводится в IP-адрес с помощьюgethostbyname . Для поиска имени функция использует DNS. Мы будем изучать технологию DNS в главе 7.
Затем создается и инициализируется сокет, после чего клиент пытается установить TCP-соединение с сервером посредствомconnect . Если сервер включен, работает на указанной машине, соединен сSERVER_PORT и либо простаивает, либо имеет достаточно места в очередиlisten (очереди ожидания), то соединение с клиентом будет рано или поздно установлено. По данному соединению клиент передает имя файла, записывая его в сокет. Количество отправленных байтов на единицу превышает требуемое для передачи имени, поскольку нужен еще нулевой байт-ограничитель, с помощью которого сервер может понять, где кончается имя файла.
Теперь клиентская программа входит в цикл, читает файл блок за блоком из сокета и копирует на стандартное устройство вывода. По окончании этого процесса она просто завершается.
Процедураfatal выводит сообщение об ошибке и завершается. Серверу также требуется эта процедура, и она пропущена в листинге только из соображений экономии места. Поскольку программы клиента и сервера компилируются отдельно и в обычной ситуации запускаются на разных машинах, код процедурыfatal не может быть разделяемым.
Читать дальшеИнтервал:
Закладка: