ПРОТОКОЛ ОБМЕНА В ПРОЕКТЕ "ФАЙЛОВЫЙ СЕРВЕР" Реализован простой файловый сервер, позволяющий просматривать список файлов в текущей директории, изменять текущую директорию, пересылать файлы серверу и получать файлы от сервера. Для передачи данных используется протокол TCP. Протокол обмена построен над протоколом TCP. Данные передаются кадрами. Кадр содержит 1) команду, которая представляется целым числом (4 байта); 2) длину поля данных (целое число, 4 байта); 3) данные -- массив байтов переменной длины. Длина поля данных может быть равна нулю и не может превышать константы const int FSR_MAXDATALEN = 2048; Структура, описывающая кадр данных: struct ProtocolFrame { int command; // Protocol action int length; // Length of data field char data[FSR_MAXDATALEN]; // Various length field }; Возможны следующие команды (все определения содержатся в заголовочном файле "filesrv.h"): const int FSR_SUCCESS = 0; // Command is performed successfully const int FSR_ERROR = 1; // Cannot perform a command const int FSR_READY = 2; // Server is ready const int FSR_DATA = 3; // Block of data, next block follows const int FSR_DATAEND = 4; // Last block of data const int FSR_PUT = 5; // Put a file const int FSR_GET = 6; // Get a file const int FSR_PWD = 7; // Pring Work Directory const int FSR_CD = 8; // Change directory const int FSR_LS = 9; // List a directory contents const int FSR_LOGOUT = 10; // End a session const int FSR_MGET = 11; // Get a set of files (Multiple get) Имена файлов во всех командах протокола передаются в кодировке Unicode UTF-16, в которой каждый символ записывается двумя байтами в формате Little Endian. ОПИСАНИЯ КОМАНД FSR_SUCCESS Передается от сервера к клиенту и означает успешное завершение запроса клиента. Она передается при успешном завершении запросов FSR_PUT и FSR_CD. Поле данных имеет нулевую длину. FSR_ERROR Передается от сервера к клиенту при ошибке. Поле данных содержит текст, описывающий ошибку. FSR_READY Передается от сервера к клиенту и означает, что сервер готов выполнить следующий запрос клиента. FSR_DATA Означает, что передается блок данных, который не является последним, т.е. за ним обязательно будет передан следующий блок. Кадр FSR_DATA может передаваться как от клиента к серверу (например, при выполнении команды FSR_PUT), так и от сервера к клиенту (при выполнении команд FSR_GET и FSR_LS). Поле length кадра содержит длину передаваемых данных (она не может превышать константы FSR_MAXDATALEN = 2048). FSR_DATAEND Означает, что передается последний блок данных, например, последняя порция содержимого файла или последняя запись в листинге директории. В остальном команда аналогична команде FSR_DATA. Прием клиентом кадра FSR_DATAEND означает успешное завершение запроса клиента, поэтому сервер в этом случае не передает команду FSR_SUCCESS. FSR_PUT Передается от клиента к серверу при запросе на передачу файла. от клиента к серверу. Поле данных содержит имя файла или путь к нему. По принятии этой команды сервер должен ответить кадром FSR_READY, означающим, что он открыл файл для записи и готов принимать содержимое файла, или FSR_ERROR, если файл не может быть открыт для записи. В первом случае клиент передает серверу содержимое файла в серии кадров FSR_DATA, заканчивающаяся кадром FSR_DATAEND. При успешной передаче файла сервер по окончанию передачи отвечает командой FSR_SUCCESS, при ошибке -- FSR_ERROR. FSR_GET Передается от клиента к серверу при запросе на прием файла от сервера. Поле данных содержит имя файла или путь к нему. Если такой файл существует на сервере и открыт на чтение, то сервер в ответ передает клиенту содержимое файла с помощью серии команд FSR_DATA, заканчивающейся командой FSR_DATAEND. В противном случае сервер отвечает командой FSR_ERROR. По окончанию передачи файла (после блока FSR_DATAEND) сервер не передает команду FSR_SUCCESS, поскольку сама по себе команда FSR_DATAEND означает успешное завершение передачи. FSR_PWD (сокращение от Print Working Directory). Передается от клиента к серверу и означает запрос полного пути к текущей директории. Поле length кадра содержит значение 0, т.е. данные в этой команде не передаются. Сервер отвечает на запрос кадром FSR_DATAEND, поле данных которого содержит путь к текущей директории на сервере. FSR_CD (сокращение от Change working Directory). Передается от клиента к серверу и означает запрос на изменение текущей рабочей директории сервера. Поле data содержит путь к новой директории. Сервер отвечает кадром FSR_SUCCESS в случае успешного выполнения команды или FSR_ERROR в случае ошибки. FSR_LS (сокращение от List). Передается от клиента к серверу и означает запрос на получения содержимого текущей директории, т.е. списка файлов и поддиректорий в текущей директории. При ошибке (когда директория закрыта на чтение) сервер передает клиенту кадр FSR_ERROR. В нормальной ситуации (директория открыта на чтение) сервер в ответ пересылает клиенту серию кадров FSR_DATA, заканчивающуюся кадром FSR_DATAEND. Каждый кадр содержит запись ровно об одном файле или поддиректории. Поле "data" кадра содержит: в первых 4-х байтах -- аттрибуты файла или поддиректории, соответствующие полю DWORD dwFileAttributes структуры WIN32_FIND_DATA, используемой при перечислении файлов в текущей директории в API Win32; в байтах начиная с пятого (смещение 4) -- имя файла или поддиректории в кодировке UTF-16, заканчивающеея нулевым символом. FSR_MGET Передается от клиента к серверу при запросе на прием множества файлов от сервера. Поле данных содержит ШАБЛОН имени файла, который может включать обычные символы и звездочку "*", означающую произвольную подстроку, не содержащую разделителей директорий "/". Протокол исполнения этой команды более сложен, чем в случаях предыдущих команд, он подробно описан ниже. ПРОТОКОЛ ВЫПОЛНЕНИЯ КОМАНДЫ FSR_MGET Выполнение команды mget начинается с передачи кадра FSR_MGET от клиента к серверу. Кадр FSR_MGET аналогичен кадру FSR_GET, только вместо имени файла он содержит шаблон имени, который может включать один или несколько символов "*", означающих вхождение произвольной подстроки, не содержащей разделителей директорий. В ответ сервер передает следующую информацию. 1. Если нет файлов, имена которых подходят под шаблон, то сервер передает кадр FSR_DATAEND, в котором поле длины содержит 0 (этот кадр означает завершение списка имен файлов, подходящих под шаблон). 2. Если список файлов, имена которых подходят под шаблон, непуст, то для каждого файла выполняется следующий обмен данными меджу сервером и клиентом: -- сервер передает клиенту кадр FSR_DATA, содержащий информацию об очередном файле. Этот кадр подобен кадру, передаваемому от сервера клиенту при выполнении команды FSR_LS, он включает тип файла (который всегда равен DT_REG) и имя файла, заканчивающеея нулевым байтом; -- дальше сервер ожидает ответа от клиента. Ответом может быть один из двух кадров: FSR_READY, если клиент готов принять очередной файл от сервера; FSR_ERROR, если клиент не готов принять файл. В этом случае выполнение команды FSR_MGET завершается. -- если клиент ответил серверу командой FSR_READY, то сервер передает клиенту содержимое файла так же, как и в случае команды FSR_GET. 3. Для завершения передачи множества файлов сервер передает клиенту кадр FSR_DATAEND, в котором поле длины содержит 0.