Организация аудио связи по локальной сети между рабочими станциями в дуплексном режиме

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    1008,76 Кб
  • Опубликовано:
    2015-01-13
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Организация аудио связи по локальной сети между рабочими станциями в дуплексном режиме

Оглавление

Введение

Сокращения и термины

. Исследовательская часть

.1 Техническое задание

.2 Анализ существующих систем организации аудиосвязи

.3 Протоколы аудиопереачи

Вывод по исследовательской части

. Конструкторская часть

.1 Архитектура сетевого взаимодействия

.2 Описание протокола передачи данных

.2.1 Взаимодействие клиента с сервером

.2.2 Взаимодействие между клиентами

.3 Алгоритм серверного приложения

.4 Структура клиентского приложения

Вывод по конструкторской части

. Технологическая часть

.1 Выбор языка программирования и средств разработки

.2 Требования к системе

.3 Описание программных модулей проекта

.3.1 Описание модулей серверного приложения

.3.2 Описание модулей клиентского приложения

.4 Описание пользовательского интерфейса

Вывод по технологической части

Заключение         

Приложения

Введение

Аудиоконференцсвязь - областьинформационной технологии <#"773310.files/image001.gif">

Рисунок 2.1. Архитектура «клиент-сервер»

Она обеспечивает централизованное управление клиентами на сервере и эффективное гарантированное взаимодействие клиентов между собой через сервер.

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

Рисунок 2.2. Архитектура «точка-точка»

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

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

.2 Описание протокола передачи данных

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

2.2.1 Взаимодействие клиента с сервером

Взаимодействие клиента с сервером требует высокой степени надежности, поэтому необходима гарантированная доставка сообщений. Для этого использовался протокол, основанный на протоколе TCP. Рассмотрим его основные аспекты.

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

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

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

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

Рисунок 2.3. Схема взаимодействия между клиентом и сервером

2.2.2 Взаимодействие между клиентами

Взаимодействие между клиентами осуществляется как по протоколу TCP, так и по протоколу UDP.

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

По протоколу UDP производится непосредственно передача аудиоданных.

При инициировании запроса на передачу данных Клиент1 отправляет сообщение ConnectToClient Клиенту2, с которым он хочет соединиться.

Клиент2, получив сообщение, соглашается или отказывается от соединения и отправляет сообщение ConnectToClientSuccess или ConnectToClientFailed соответственно. Если соединение установлено, то начинается передача видео- и аудиоданных по протоколу UDP.

Если Клиент1 хочет прекратить передачу данных - он отправляет Клиенту2 сообщение DisconnectRequest, после чего оба клиента прекращают передачу медиаданных.

Схема взаимодействия между клиентами представлена на рисунке 2.4.

Рисунок 2.4. Взаимодействие между клиентами

2.3 Алгоритм серверного приложения


Серверное приложение выполняет управляющую функцию, функцию координатора клиентов, а также ведет журналирование.

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

Если тип пакета = AuthorizationRequest, то происходит регистрация нового пользователя на сервере.

При получении пакета с типом ConnectToClientRequest - происходит передача информации о клиенте, который хочет подключиться клиенту, к которому он хочет подключиться.

Получив пакет с типом IQuit - удаляет пользователя из списка активных пользователей и отсылает всем клиентам сообщение об отключившемся пользователе.

Также сервер осуществляет сбор информации обо всех действиях, произведенных на сервере. Полученные данные записывает в файл на жестком диске.

Алгоритм работы сервера показан на рисунке 2.5.

Рисунок 2.5. Блок схема алгоритма работы сервера

2.4 Структура клиентского приложения


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

После отправки клиентом серверу запроса на подключение, клиент может получить одно из следующих сообщений: AuthorizationSuccess, AuthrizationFailed. В случае сообщений первого типа - клиент успешно авторизован на сервере, он получает список доступных пользователей. Во втором случае авторизация была неудачна и на экран выводится сообщение с причиной неудачи.

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

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

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

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

Получив такой пакет, клиент читает информацию о пользователе и инициирует видеопередачу.

Если пользователь не готов или не желает начать видеопередачу - он отправляет пакет с типом ConnectToClientFailed, получив который, другой клиент уведомляет пользователя об отказе в соединении.

При завершении аудиопередачи, клиент получает сообщение DisconnectRequest и прекращает передачу данных.

Алгоритм работы клиента показан на рисунке 2.6.

Рисунок 2.6. Блок-схема алгоритма работы клиента

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

В дальнейшем необходимо будет реализовать программный комплекс с заданным для него функционалом, который был указан в пункте 2.1., для взаимодействия между частями                 системы необходимо использовать протокол, описанный в пункте 2.2. Алгоритмы работы сервера и клиента были описаны в пунктах 2.3. и 2.4.

3. Технологическая часть

.1 Выбор языка программирования и средств разработки

При разработки приложения-сервера и приложения-клиента использовался язык программирования высокого уровня C# и среда визуального программирования Microsoft Visual Studio 2010. Выбор был обусловлен удобством C# при использовании объектно-ориентированного подхода, а так же тем набором необходимых средств и конструкций, которыми он располагает, а VS 2010 была выбрана из-за большого разнообразия библиотек и классов, в том числе и для сетевого программирования, и простоты реализации пользовательского интерфейса.

3.2 Требования к системе


Для нормального функционирования программного комплекса система должна удовлетворять следующим требованиям:

·           операционная система Windows XP, Windows Vista, Windows 7;

·        установленный.NET Framework 3.0;

·        библиотека Voice.dll;

·        наличие микрофона (встроенного или внешнего).

3.3 Описание программных модулей проекта

 

.3.1 Описание модулей серверного приложения

Серверное приложение абстрактно можно представить в виде трех модулей.

Модуль создания соединений - основной модуль серверного приложения. Он представлен классом Server, листинг которого отражен в приложении.

Класс содержит информацию о сервере - адрес и порт, сокет для приема и передачи данных клиентам. Также в классе содержится главный поток серверного приложения, который принимает запросы на подключение клиентов, список установленных соединений - объектов класса Connection. В сервере хранится список зарегистрированных пользователей. Здесь же инициализируется объект LogWriter, который отвечает за ведение журнала событий.

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

Модуль обслуживания соединений - модуль, задачей которого является осуществление связи между клиентом и сервером. Он представлен классом Connection, листинг которого отражен в приложении.

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

Модуль сбора статистики необходим для осуществления контроля действий, происходящих на сервере. Модуль представлен классом LogWriter, листинг которого представлен в приложении.

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

3.3.2 Описание модулей клиентского приложения

Клиентское приложение абстрактно можно представить в виде трех модулей.

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

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

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

Модуль представлен двумя классом AudioTranceiver, который реализует соответственно передачу и получение аудиоданных.

 

.4 Описание пользовательского интерфейса


Основу пользовательского интерфейса составляет главное окно клиентского приложения. Его вид представлен на рисунке 3.1.

Рисунок 3.1. Главное окно клиентского приложения

В центре главного окна располагается список пользователей, подключенных к конференции.

Вверху располагается меню. Вкладка «Конференция» имеет подпункты «Подключение», «Отключение» и «Выход». (см. Рисунок 3.2.).

Рисунок 3.2. Меню «Файл»

При нажатии на пункт «Подключение» появляется диалоговое окно «Подключение» (см. рисунок 3.3.), с помощью которого можно осуществить подключение к серверу. В этом диалоговом окне расположены поле для ввода имени компьютера, на котором располагается сервер, поля для ввода логина и пароля пользователя.

Рисунок 3.3. Диалоговое окно «Подключение»

Интерфейс серверного приложения крайне прост. Его вид представлен на рисунке 3.4.

Рисунок 3.4. Интерфейс серверного приложения

В центре окна располагаются поля выбора IP сервера из имеющихся (получаемых программно) и для ввода пароля для входа на сервер. Меню «Сервер» имеет подпункты «Включить», «Отключить» и «Выход» (см. Рисунок 3.5).

Рисунок 3.5. Меню «Файл»

3.5 Результаты тестирования разработанного средства


В процессе тестирования было проверено, правильно ли работают клиент и сервер при штатном использовании и нештатных ситуациях.

.         При запуске сервера появляется окно авторизации (рисунок 3.5.1.)

Рис. 3.5.1. Окно авторизации

.         При неверном пароле (рисунок 3.5.2) приложение не запустится.

Рис. 3.5.2. Сообщение о неверном пароле при запуске сервера

.         При неверной авторизации пользователя, в случаях, если пароль неверен или пользователь с таким именем уже есть в сети, на экране появятся соответствующие сообщения (рисунки 3.5.3 и 3.5.4).

Рис. 3.5.3. Сообщение клиенту о неверном пароле.

Рис. 3.5.4. Сообщение клиенту о неверном логине.

А также появятся соответствующие записи в журнале об этом:

.12.2011 23:04:06: Авторизация пользователя Mendax неуспешна. Неправильный пароль.

.12.2011 23:03:20: Авторизация пользователя Mendax неуспешна. Неправильное имя пользователя.

.         Если сервер выключается, на экране клиентов выдается сообщение об ошибке (рисунок 3.5.5).

При верной авторизации клиент подключится к серверу, имя клиента добавится в список активных пользователей и будет добавлена запись в журнал: “04.12.2011 18:36:39: Авторизация пользователя Mendax прошла успешно”.

Рис. 3.5.2. Сообщение клиенту об отключении сервера.

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

Для сервера был реализован следующий функционал:

.         Автоматический поиск IP-адресов, на которых может быть запущен сервер;

.         Запуск сервера;

.         Остановка сервера;

.         Журналирование. Используется файл serverLog.txt;

.         Просмотр и удаление файла журнала.

Для клиента был реализован следующий функционал:

)        Подключение к серверу;

)        Отключение от сервера;

)        Подключение к пользователю;

)        Отключение от пользователя;

)        Передача аудио-данных от пользователя к пользователю;

)        Уведомления о произошедших ошибках, возникших в процессе работы. Они реализованы в виде всплывающих окон.

Заключение


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

Программный комплекс состоит из:

. Клиентского приложения;

. Серверного приложения.

В ходе разработки данного программного комплекса были выполнены следующие требования:

1. Разработка протокола высокого уровня для организации взаимодействия клиент-сервер;

2. Разработка пользовательского интерфейса;

. Организация аудиосвязи между клиентами.

Разработанный программный комплекс удовлетворяет всем требованиям, выдвинутым в техническом задании. Однако он обладает некоторыми недостстками. Например, остутствие связи один ко многим и многие ко многим.

Приложения

Клиент:System;System.Collections.Generic;System.Linq;System.Text;System.Net;System.Net.Sockets;System.Threading;System.Windows.Forms;Client

{

public delegate void NeedListRedraw();

public delegate void EmptyHandler();Client

{

frmClient form;

String nickName;

String password;

Socket socket;

Thread mainThread;

public String connectedUser = "";

public List<String> connectedUsers;

AudioTransceiver audiotransceiver;isTransfering;Client(String _nickName, String _password, frmClient _form)

{

nickName = _nickName;

password = _password;

form = _form;

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,

ProtocolType.Tcp);

connectedUsers = new List<string>();

}String GetUserName()

{

return nickName;

}void Connect(String hostName)

{

//Подключаемся к серверу

socket.Connect(hostName, 11000);port = ((IPEndPoint)socket.LocalEndPoint).Port - 1000;

IPAddress ipAddress = ((IPEndPoint)socket.LocalEndPoint).Address;

audiotransceiver = new AudioTransceiver(ipAddress, port);messageType = (byte)Messages.AuthorizationRequest;

SocketWriter.WriteType(socket, (byte)messageType);

SocketWriter.WriteString(socket, password);

User userToWrite = new User(nickName, new IPEndPoint(ipAddress, 11100));

SocketWriter.WriteUserRecord(socket, userToWrite);.AudioEndHandler = new EmptyHandler(AudioEnd);= new Thread(MainThread);

mainThread.IsBackground = true;

mainThread.Start();

}

void AudioEnd()

{

}

public void Stop()

{

try

{

SocketWriter.WriteType(socket, (byte)Messages.IQuit);

socket.Disconnect(false);

if (audiotransceiver != null)

audiotransceiver.Dispose();

mainThread.Abort();

}

catch { }

}MainThread()

{

try

{

while (true)

{

byte messageType = SocketReader.ReadType(socket);

switch (messageType)

{

case (byte)Messages.AuthorizationFailed:

{

messageType = SocketReader.ReadType(socket);

if (messageType == (byte)Messages.WrongPassword)

{

MessageBox.Show("Неверный пароль");

form.Invoke(form.disconnect);

}

else if (messageType == (byte)Messages.WrongName)

{

MessageBox.Show("Пользователь с таким именем уже есть

в сети");

form.Invoke(form.disconnect);

}

break;

}

case (byte)Messages.AuthorizationSuccess:

{

int userNum = SocketReader.ReadInt(socket);

for (int i = 0; i < userNum; i++)

{

connectedUsers.Add(SocketReader.ReadString(socket));

}

form.Invoke(form.redrawList);

break;

}

case (byte)Messages.ClientConnected:

{

NewClientConnected();

form.Invoke(form.redrawList);

break;

}

case (byte)Messages.ClientDisconnected:

{

ClientDisconnected();

form.Invoke(form.redrawList);

break;

}

case (byte)Messages.ConnectToClientRequest:

{

ConnectToClientRequest();

form.Invoke(form.redrawList);

break;

}

case (byte)Messages.ConnectToClientSuccess:

{

ConnectToClientSuccess();

form.Invoke(form.redrawList);

break;

}

case (byte)Messages.ConnectToClientFailed:

{

ConnectToClientFailed();

form.Invoke(form.redrawList);

break;

}

case (byte)Messages.DisconnectRequest:

{

connectedUser = "";

form.Invoke(form.redrawList);

DisconnectAudio();

break;

}

case (byte)Messages.ServerClose:

{

MessageBox.Show("Сервер отключен. Соединение прервано.");

DisconnectAudio();

form.Invoke(form.disconnect);

return;

}(ThreadAbortException e)

{(Exception e)

{

MessageBox.Show("Соединение будет закрыто." + e.Message);

Stop();

}ConnectToClientRequest()

{

User requestingUser = SocketReader.ReadUserRecord(socket);

if (MessageBox.Show("Пользователь " + requestingUser.nickName + " хочет осуществить подключение к вам. Одобрить подключение?", "Запрос на подключение", MessageBoxButtons.YesNo) == DialogResult.Yes)

{

SocketWriter.WriteType(socket, (byte)Messages.ConnectToClientSuccess);

SocketWriter.WriteUserRecord(socket, requestingUser.nickName,

audiotransceiver.GetEndPoint().Address.ToString(),

audiotransceiver.GetEndPoint().Port);

connectedUser = requestingUser.nickName;

audiotransceiver.Connect(requestingUser.ipEndPoint);

audiotransceiver.BeginTransceiving();

}

else

{

SocketWriter.WriteType(socket, (byte)Messages.ConnectToClientFailed);

SocketWriter.WriteString(socket, requestingUser.nickName);

}

}ConnectToClientSuccess()

{

User user = SocketReader.ReadUserRecord(socket);

audiotransceiver.Connect(user.ipEndPoint);

audiotransceiver.BeginTransceiving();

connectedUser = user.nickName;

}ConnectToClientFailed()

{

MessageBox.Show("Пользователь отверг подключение");

}void DisconnectAudio()

{

try

{

if (audiotransceiver != null)

{

audiotransceiver.EndTransceiving();

//audiotransceiver.Dispose();

}

}

catch

{

}

// }

}NewClientConnected()

{

User user = SocketReader.ReadUserRecord(socket);

connectedUsers.Add(user.nickName);

form.Invoke(form.redrawList);

}

void ClientDisconnected()

{

//Читаем имя отсоединившегося пользователя

String name = SocketReader.ReadString(socket);

//Удаляем его из списка

connectedUsers.Remove(name);

}

public void SendConnectRequest(String userName)

{

SocketWriter.WriteType(socket, (byte)Messages.ConnectToClientRequest);

SocketWriter.WriteUserRecord(socket, userName,

audiotransceiver.GetEndPoint().Address.ToString(), audiotransceiver.GetEndPoint().Port);

}

public void SendDisconnectRequest(String userName)

SocketWriter.WriteType(socket, (byte)Messages.DisconnectRequest);

SocketWriter.WriteString(socket, userName);

//EndTranslation1();

}

public void EndTranslation1()

{

connectedUser = "";

}

}

}

Сервер:System;System.Collections.Generic;System.Linq;System.Text;System.Net;System.Net.Sockets;System.Threading;System.Windows.Forms;Server

{

class Server

{

private Socket socket;

private IPAddress ipAddress;

private int port;

private Thread mainThread;

private LogWriter logWriter;

private List<User> users;

private List<Connection> connections;

private string password;Server(String _ipAddress, int _port, String _logFileName, String _password)

{

ipAddress = IPAddress.Parse(_ipAddress);

port = _port;

logWriter = new LogWriter(_logFileName);

users = new List<User>();

connections = new List<Connection>();

password = _password;

}void Start()

{

//Устанавливаем локальную конечную точку

IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);

//Создаем сокет, привязываем его к конечной точке и начинаем прослушивание

socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

socket.Bind(ipEndPoint);

socket.Listen(10);

//Создаем поток для приема соединений от клиентов

mainThread = new Thread(MainThread);

mainThread.IsBackground = true;

mainThread.Start();

// сообщаем об этом логу

logWriter.WriteToLogFile("Сервер запущен. IP-адрес: " + ipAddress.ToString() +

" Порт: " + port.ToString());

}void Stop()

{

//Посылаем всем сообщения что сервер остановлен

foreach (Connection connection in connections)

SendMessage(connection, Messages.ServerClose);

//Удаляем соединения

connections.Clear();

//Закрываем сокет, завершаем поток

socket.Close();

mainThread.Abort();

// пишем об этом в лог

logWriter.WriteToLogFile("Сервер остановлен");

}void MainThread()

{

try

{

while (true)

{

//Ждем соединения

Socket connectionSocket = socket.Accept();

//Принимаем соединение

Connection connection = new Connection();

connection.socket = connectionSocket;

logWriter.WriteToLogFile("Новое соединение. " + .RemoteEndPoint.ToString());

//Создаем поток соединения

connection.thread = new Thread(ConnectionThread);

connection.thread.IsBackground = true;

connection.thread.Start(connection);

//Добавляем соединение в список

connections.Add(connection);

}

}

catch (ThreadAbortException e)

{

}

catch (Exception e)

{

Stop();

}

}void ConnectionThread(object param)

{

//Параметр в поток - объект соединения

Connection connection = (Connection)param;

try

{

while (true)

{

//Читаем тип сообщения

byte messageType = SocketReader.ReadType(connection.socket);

//Делаем что требуют

switch (messageType)

{

case (byte)Messages.AuthorizationRequest:

{

if(!Authorization(connection))

return;

break;

}

case (byte)Messages.ConnectToClientRequest:

{

ConnectToClientRequest(connection);

break;

}

case (byte)Messages.ConnectToClientSuccess:

{

ConnectToClientSuccess(connection);

break;

}

case (byte)Messages.ConnectToClientFailed:

{

ConnectToClientFailed(connection);

break;

}

case (byte)Messages.DisconnectRequest:

{

DisconnectRequest(connection);

break;

}

case (byte)Messages.IQuit:

{

DisconnectUser(connection);

return;

}(Exception e)

{

logWriter.WriteToLogFile("Исклчение: " + e.Message);

//MessageBox.Show("Exception: " + e.Message);

}

finally

{

//DisconnectUser(connection);

}

}

//Клиент хочет подключиться

private void ConnectToClientRequest(Connection connection)

{

User requestedUser = SocketReader.ReadUserRecord(connection.socket);

logWriter.WriteToLogFile("Запрос на подключение от пользователя " + .userNickName + " пользователю " + requestedUser.nickName);

foreach (Connection _connection in connections)

{

if (_connection.userNickName == requestedUser.nickName)

{

SendMessage(_connection, Messages.ConnectToClientRequest);

//SocketWriter.WriteString(_connection.socket, .userNickName);

SocketWriter.WriteUserRecord(_connection.socket, .userNickName,

requestedUser.ipEndPoint.Address.ToString(),

requestedUser.ipEndPoint.Port);

return;

}

//Клиент одобрил подключение

private void ConnectToClientSuccess(Connection connection)

{

User requestingUser = SocketReader.ReadUserRecord(connection.socket);

foreach (Connection _connection in connections)

{

if (_connection.userNickName == requestingUser.nickName)

{

SendMessage(_connection, Messages.ConnectToClientSuccess);

SocketWriter.WriteUserRecord(_connection.socket, .userNickName,

requestingUser.ipEndPoint.Address.ToString(),

requestingUser.ipEndPoint.Port);

return;

}

//Клиент не одобрил подключение

private void ConnectToClientFailed(Connection connection)

{

String requestingUser = SocketReader.ReadString(connection.socket);

foreach (Connection _connection in connections)

{

if (_connection.userNickName == requestingUser)

{

SendMessage(_connection, Messages.ConnectToClientFailed);

return;

}void DisconnectRequest(Connection connection)

{

String requestingUser = SocketReader.ReadString(connection.socket);

logWriter.WriteToLogFile("Запрос на отключение от пользователя " + .userNickName + " пользователю " + requestingUser);

foreach (Connection _connection in connections)

{

if (_connection.userNickName == requestingUser || _connection.userNickName

== connection.userNickName)

{

SendMessage(_connection, Messages.DisconnectRequest);

//return;

}

//Клиент прислал запрос авторизации

private bool Authorization(Connection connection)

{

String userPassword = SocketReader.ReadString(connection.socket);

User user = SocketReader.ReadUserRecord(connection.socket);

logWriter.WriteToLogFile("Авторизация пользователя " + user.nickName);

//Проверяем пароль

if (userPassword != password)

{

SendMessage(connection, Messages.AuthorizationFailed);

SendMessage(connection, Messages.WrongPassword);

logWriter.WriteToLogFile("Авторизация пользователя " + user.nickName + "

неуспешна. Неправильный пароль.");

connections.Remove(connection);

return false;

}

//Проверяем на наличие такого имени

foreach (User _user in users)

{

if (_user.nickName == user.nickName)

{

SendMessage(connection, Messages.AuthorizationFailed);

SendMessage(connection, Messages.WrongName);

logWriter.WriteToLogFile("Авторизация пользователя " + user.nickName +

" неуспешна. Неправильное имя пользователя.");

connections.Remove(connection);

return false;

}

//Если все удачно, добавляем пользователя

users.Add(user);

SendMessage(connection, Messages.AuthorizationSuccess);

logWriter.WriteToLogFile("Авторизация пользователя " + user.nickName + "

прошла успешно");

connection.userNickName = user.nickName;

//Передаем список имен

SocketWriter.WriteInt(connection.socket, connections.Count);

foreach (Connection _connection in connections)

{

SocketWriter.WriteString(connection.socket, _connection.userNickName);

}

//Посылаем всем пользовтелям сообщение об авторизации нового пользователя

foreach (Connection _connection in connections)

{

if (connection != _connection)

{

SendMessage(_connection, Messages.ClientConnected);

SocketWriter.WriteUserRecord(_connection.socket, user);

}true;

}

//Отключение пользователя

private void DisconnectUser(Connection connection)

{

//Удаляем пользователя из списка

foreach (User user in users)

{

if (connection.userNickName == user.nickName)

{

users.Remove(user);

logWriter.WriteToLogFile("Пользователь " + connection.userNickName + "

отключился");

break;

}

//Всем пользователям отправляем сообщение об отключении пользователя

foreach (Connection _connection in connections)

{

if (_connection != connection)

{

SendMessage(_connection, Messages.ClientDisconnected);

SocketWriter.WriteString(_connection.socket, connection.userNickName);

}

//connection.socket.Shutdown(SocketShutdown.Both);

connection.socket.Close();

connections.Remove(connection);

}void SendMessage(Connection connection, Messages messageType)

{

SocketWriter.WriteType(connection.socket, (byte)messageType);

}

Похожие работы на - Организация аудио связи по локальной сети между рабочими станциями в дуплексном режиме

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!