Чтение онлайн

на главную - закладки

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

• С сервером одновременно может взаимодействовать только один клиент (этот недостаток легко устранить).

• Сервер может только отправлять файлы, но не может получать.

• Отсутствуют условия для ввода ограничений на передачу файлов анонимному удаленному пользователю.

• Выполняется очень поверхностная проверка ошибок, что, скорее всего, приведет к проблемам во время эксплуатации.

Клиент tftp начинает tftp-сеанс передачей "пакета запроса на чтение", содержащего имя файла, который нужно получить, и режим. Существует два исходных режима:

netascii
(выполняет некоторые простые преобразования файла) и
octet
(передает файл точно в таком же состоянии, в каком он находится на диске). Рассматриваемый
сервер поддерживает только режим
octet
, поскольку он проще.

При получении запроса для чтения tftp-сервер посылает файл (512 байт за один раз). Каждая дейтаграмма содержит номер блока (нумерация начинается с единицы). Когда клиент получает блок данных, содержащий менее 512 байтов, он знает, что файл получен должным образом. После каждой дейтаграммы клиент посылает ответную дейтаграмму с номером блока, подтверждающую, что данный блок успешно получен. Как только сервер видит подтверждение, он отправляет следующий блок данных.

Основной формат дейтаграммы определен в строках 17-46. Некоторые константы указывают тип посылаемой дейтаграммы, а также код ошибки, отправляемой в том случае, если запрашиваемый файл не существует (все остальные ошибки обрабатываются непосредственно сервером). Структура

struct tftpPacket
описывает внешний вид дейтаграммы и код операции, следующей за данными, которая зависит от типа дейтаграммы. Затем логическое объединение, вложенное в структуру, определяет остальные форматы дейтаграмм для ошибок, данных и пакетов подтверждения.

Первая часть

main
(строки 156—169) создает UDP-сокет и устанавливает номер локального порта с помощью вызова
bind
. Последний является либо официальной tftp-службой, либо портом, указанным в качестве единственного аргумента командной строки программы. В отличие от нашего примера TCP-сервера здесь нет необходимости вызывать ни
listen
, ни
accept
, поскольку UDP работает без установки соединений.

После создания сокета сервер ожидает получение дейтаграммы путем вызова

recvfrom
. Функция
handleRequest
, которая активизируется в строке 181, преобразует запрашиваемый файл и возвращает его. После этого вызова сервер еще раз активизирует
recvfrom
и ожидает запрос от следующего клиента.

Комментарий, расположенный перед вызовом

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

В то время как главная часть программы использует неподключенный UDP-сокет (позволяющий любому клиенту соединение с ним),

handleSocket
применяет для преобразования файла подключенный UDP-сокет [144] . После анализа имени файла, который нужно передать, и проверки правильности режима преобразования в строке 93 создается сокет с тем же самым семейством, типом и протоколом, с которыми контактировал сервер. Затем используется
connect
для установки удаленного конца сокета на том адресе, от которого поступил запрос на файл, и начинается передача файла. После отправки каждого блока сервер ожидает пакет подтверждения, прежде чем продолжить передачу. Когда приходит последний пакет подтверждения, сервер закрывает сокет и возвращается к главному циклу.

144

Спецификация tftp-протокола требует, чтобы серверы посылали данные клиенту на номер порта, отличающийся от порта, на котором сервер ожидает новые соединения. При этом нетрудно создать параллельный сервер, поскольку каждый сокет сервера предназначен только для одного клиента.

Данный сервер, как правило, запускается с единственным аргументом —

номером порта. Для проверки можно применить стандартную клиентскую программу
tftp
, где первый аргумент является именем хоста для соединения (неплохим выбором будет
localhost
), а второй — номером порта, на котором работает сервер. После запуска клиента нужно активизировать команду
bin
, при этом файлы будут запрашиваться в режиме
octet
, а не в стандартном режиме
netascii
. Как только это сделано, команда
get
позволит передать любой файл от сервера клиенту.

1: /* tftpserver.c */

2:

3: /* Это частичная реализация tftp. Она не поддерживает даже тайм-ауты

4: или повторную передачу пакетов, и она не очень хорошо

5: обрабатывает непредвиденные события.*/

6:

7: #include <netdb.h>

8: #include <stdio.h>

9: #include <stdlib.h>

 10: #include <string.h>

 11: #include <sys/socket.h>

 12: #include <unistd.h>

 13: #include <fcntl.h>

 14:

 15: #include "sockutil.h" /* некоторые служебные функции */

 16:

 17: #define RRQ 1 /* запрос на чтение */

 18: #define DATA 3 /* блок данных */

 19: #define ACK 4 /* подтверждение */

 20: #define ERROR 5 /* возникла ошибка */

 21:

 22: /* коды ошибок tftp */

 23: #define FILE_NOT_FOUND 1

 24:

 25: struct tftpPacket {

 26: short opcode;

 27:

 28: union {

 29: char bytes[514]; /* самый большой блок, который мы

 30: можем обработать, содержит 2 байта

 31: для номера блока и 512 для данных */

 32: struct {

 33: short code;

 34: char message[200];

 35: } error;

 36:

 37: struct {

 38: short block;

 39: char bytes[512];

 40: } data;

 41:

 42: struct {

 43: short block;

 44: } ack;

 45: } u;

 46: };

 47:

 48: void sendError(int s, int errorCode) {

 49: struct tftpPacket err;

 50: int size;

 51:

 52: err.opcode = htons(ERROR);

 53:

 54: err.u.error.code = htons(errorCode); /* файл не найден */

 55: switch (errorCode) {

 56: case FILE_NOT_FOUND:

 57: strcpy(err.u.error.message, "файл не найден");

Поделиться:
Популярные книги

Законы Рода. Том 4

Flow Ascold
4. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 4

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Попаданка в семье драконов

Свадьбина Любовь
Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.37
рейтинг книги
Попаданка в семье драконов

Враг из прошлого тысячелетия

Еслер Андрей
4. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Враг из прошлого тысячелетия

Рота Его Величества

Дроздов Анатолий Федорович
Новые герои
Фантастика:
боевая фантастика
8.55
рейтинг книги
Рота Его Величества

Девятое правило дворянина

Герда Александр
9. Истинный дворянин
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Девятое правило дворянина

На границе империй. Том 5

INDIGO
5. Фортуна дама переменчивая
Фантастика:
боевая фантастика
попаданцы
7.50
рейтинг книги
На границе империй. Том 5

Неудержимый. Книга X

Боярский Андрей
10. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга X

Убивать чтобы жить 2

Бор Жорж
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 2

Невеста

Вудворт Франциска
Любовные романы:
любовно-фантастические романы
эро литература
8.54
рейтинг книги
Невеста

Кодекс Охотника. Книга XVI

Винокуров Юрий
16. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVI

Последний рейд

Сай Ярослав
5. Медорфенов
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Последний рейд

Чужое наследие

Кораблев Родион
3. Другая сторона
Фантастика:
боевая фантастика
8.47
рейтинг книги
Чужое наследие