Разработка программы обмена файлами между пользователями локальной сети

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 19:41, 12 января 2016.

Целью курсовой работы является разработка программы для передачи файлов между двумя произвольными компьютерами, соединенными через локальную сеть. Программа должна:

  • обеспечивать авторизацию пользователя
  • осуществлять передачу данных между пользователями
  • вести журнал событий
  • обрабатывать ошибочные ситуации

Курсовая работа была выполнена студентами ИУ7-73 Ивановым И.В. и Столяренко А.В.

Введение

При разработке использовался язык программирования C# на платформе .NET Framework. Такой выбор был сделан из-за богатой стандартной библиотеки платформы.

При запуске приложения происходит установка соединения с сервером авторизации, после чего в появившемся окне пользователь должен ввести свои логин и пароль. После авторизации взаимодействия с сервером авторизации не происходит.

После авторизации пользователь должен подключиться к каналу мультивещания (multicast). Мультивещание используется для составления списка активных пользователей без необходимости запросов к серверу. Раз в N секунд (период указывается в файле конфигурации) в группу мультивещания отправляется сообщение «я жив»; если от клиента не приходит таких сообщений в течение 3*N секунд, считается, что клиент отключился из-за разрыва связи.

Список активных пользователей формируется из их IP-адресов. Выбрав нужный адрес, пользователь может выбрать файл и инициировать его передачу.

В приложении выполняется обработка следующих внештатных ситуаций:

  1. Разрыв соединения при передаче файла (в том числе и при отмене передачи принимающей стороной)
  2. Ввод неправильного логина и/или пароля
  3. Нехватка места на диске для приёма файла

Пользовательский интерфейс

Пользовательский интерфейс приложения

Форма приложения реализует интерфейс IUIWorker, предоставляющий следующие методы:

void Report(string message)

Показывает пользователю окно (MessageBox) с сообщением.

string GetFileName(string ipAddress, string suggestedFileName)

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

void UpdateStatus(string message)

Обновляет строку статуса на форме.

void UpdateProgress(int value)

Обновляет значение полосы прогресса передачи файла.

Использование мультивещания

Для рассылки запросов мультивещания используется класс MulticastManager. При работе с созданным экземпляром менеджера используются следующие методы:

public void JoinMulticast()

Подключает клиента к группе мультивещания. Из файла конфигурации считываются адрес и порт мультивещания; создаются сокеты для приёма и отправки данных; запускается таймер, раз в N отправляющий в группу мультивещания сообщение «alive».

public void LeaveMulticast()

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

public delegate void ConnectionHandler(AddressState state);
public event ConnectionHandler Connection;

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

Отправка файла

Для отправки файла используется класс TcpFileSender. Используются следующие методы:

public TcpFileSender(IPAddress address, IUIWorker uiWorker)

Создаёт экземпляр класса на основе IP-адреса получателя и формы интерфейса. Создаётся сокет для потоковой передачи данных по протоколу TCP в пределах локальной сети.

public bool SendFile(string fileName)

Передача файла с указанным именем. Осуществляется в четыре этапа:

  1. Расчёт и отправка хэш-суммы файла
  2. Отправка размера файла
  3. Отправка названия
  4. Непосредственно отправка самого файла

В случае неудачи на любом из этапов возвращается false, иначе – true.

Прием файла

Для приёма файла используется связка из двух классов: TcpFileListener и TcpFileReceiver. Первый используется при ожидании входящего соединения и запроса на передачу файла, второй – для непосредственно приёма данных.

Используемые методы TcpFileListener:

public TcpFileListener(IUIWorker uiWorker)

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

После приема подключения создаётся экземпляр TcpFileReceiver и принимается предварительная информация о файле (хэш-сумма, размер, имя файла). Если на диске не хватает места для сохранения файла, будет выведено соответствующее сообщение и прием файла инициирован не будет.

Используемые методы TcpFileReceiver:

public TcpFileReceiver(Socket acceptedSocket, IUIWorker uiWorker)

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

public bool GetFile(string filename)

Прием файла (блоками байт в соответствие с протоколом TCP) и сохранение его по указанному пути. После получения файла происходит сравнение его хэш-суммы с присланной ранее; в случае совпадения возвращается true, иначе – false.

В случае разрыва соединения, исключение SocketException перехватывается в пределах функции и выводится информационное сообщение.

Журнал событий

Для ведения журнала событий используется библиотека NLog, являющаяся де-факто стандартом для записи журнала событий в приложениях для .NET Framework. Библиотека позволяет использовать сообщения различного уровня важности (трассировочные, отладочные, информационные, предупреждения, ошибки и многие другие).

Форматы и способы вывода данных задаются в файле конфигурации Nlog.config. Библиотека отличается большим количеством настроек: к примеру, сообщения могут записываться в файл на диске, в базу данных или отображаться на управляющей форме. Кроме того, пользователь может оставить запись только для сообщений определенного уровня важности (например, только для ошибок).

Пример файла конфигурации:

1]  <targets>
2]    <target xsi:type="File" name="fileLogging" fileName="${shortdate}.log"
3]            layout="${longdate} ${message}" />
4]  </targets>
5]
6]  <rules>
7]    <logger name="*" minlevel="Debug" writeTo="fileLogging" />
8]  </rules>

В строке 2 мы указываем, что «целью» записи будет файл, даём «цели» имя и указываем путь к файлу. В строке 3 мы указываем формат, в котором будут выводиться сообщения. В строке 7 мы определяем правило, согласно которому любой объект-логгер должен перенаправлять сообщения уровнем не ниже отладочных в «цель» “fileLogging”.

Для использования библиотеки необходимо обращаться к экземпляру класса Logger, получить который можно с помощью вызова статической функции LogManager.GetCurrentClassLogger(). Пример использования:

private static readonly Logger log = LogManager.GetCurrentClassLogger();
...
catch (ObjectDisposedException ex)
{
    log.Debug( " > Ожидаемое исключение при уничтожении сокета." + Environment.NewLine + ex );
}
catch (Exception ex)
{
    log.Error( " ! Ошибка при получении сообщения!" + Environment.NewLine + ex);
}

Авторизация

Для авторизации используется фреймворк WCF, который абстрагирует весь уровень обмена сообщениями между несколькими приложениями. В приложении сервера авторизации определён интерфейс IAutenthificator:

[ServiceContract]
public interface IAutenthificator
{
    [OperationContract]
    bool Authentificate(string login, byte[] password);
}

Для клиента средствами Visual Studio автогенерируется код класса, сериализующего входные данные, отправляющего их серверу и десериализующего ответ. Для проверки данных аутентификации на стороне сервера используется база данных в СУБД MS SQL, хранящая идентификатор пользователя, логин и SHA-1 хэш пароля. Для работы с базой используется ORM Entity Framework 6.

Реализация метода Authentificate на сервере заключается в нахождении пользователя с таким логином в базе данных и сверке пришедшего хэша и хэша в БД. SHA-1 хэш пароля считается на клиенте перед передачей в метод Authentificate. Проверка логина и пароля осуществляется один раз при старте приложения, IP-адрес сервера аутентификации хранится в файле конфигурации. Если с сервером аутентификации не удалось соединиться, пользователю будет отказано в использовании приложения.