35351

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

Курсовая

Информатика, кибернетика и программирование

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

Украинкский

2014-03-24

584.5 KB

9 чел.

PAGE   \* MERGEFORMAT27

Федеральное агентство по образованию

Государственное образовательное учреждение высшего профессионального образования

«Московский государственный технический университет имени Н.Э. Баумана» (МГТУ им. Н.Э. Баумана)

Факультет «Информатика и системы управления»

Кафедра «Программное обеспечение ЭВМ и информационные технологии»

РАСЧЕТНО-ПОЯСНИТЕЛЬНАЯ ЗАПИСКА

к курсовой работе по курсу

«Вычислительные комплексы и сети»

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

Студенты:  Федянин Р. В.

Сафин И. А.  Группа: ИУ7-72

Научный руководитель: Алешин В. А.

Москва, 2011


Оглавление

[1] Оглавление

[2] Введение

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

[4]
1. Исследовательская часть

[4.1] 1.1. Техническое задание

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

[4.3] 1.3. Протоколы аудиопереачи

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

[5]
2. Конструкторская часть

[5.1] 2.1. Архитектура сетевого взаимодействия

[5.2] 2.2. Описание протокола передачи данных

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

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

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

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

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

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

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

[6.2] 3.2. Требования к системе

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

[6.3.1] 3.3.1. Описание модулей серверного приложения

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

[6.4] 3.4. Описание пользовательского интерфейса

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

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

[7]
Заключение

[8] Список использованной литературы

[9]
Приложения

Введение

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

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


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

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

TCP (Transmission Control Protocol) – ориентированный на соединение протокол, направленный на обеспечение надежной передачи данных между процессами, выполняемыми на одном или разных компьютерах.

UDP (User Datagram Protocol) – простой ориентированный на дейтаграммы протокол без организации соединения, предоставляющий быстрое, но необязательно надежное транспортное обслуживание.

Клиент – компьютер, имеющий удаленный доступ к информации и программам, хранящимся на сервере.

Сервер – компьютер, на котором хранится информация, предоставляемая по удаленному доступу клиентам.


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

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

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

  •  Система ориентирована на семейство операционных систем Windows;
  •  Предусмотреть  аутентификацию  и  авторизацию  пользователя  на сервере;
  •  Должно быть реализовано ведение журнала для сервера.

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

Skype (http://www.skype.com/intl/ru/get-skype) 

Skype (последняя версия 5.5.0.124, страна-производитель: США, компания Microsoft, 2011г.) – бесплатное проприетарное программное обеспечение с закрытым кодом, обеспечивающее шифрованную голосовую связь через Интернет между компьютерами (VoIP), а также платные услуги для связи с абонентами обычной телефонной сети.

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

Недостатки:

  •  В процессе работы Skype генерирует типичный для P2P-сетей и неизбежный постоянный трафик, который может достигать гигабайта в месяц.
  •  Skype — это чёрный ящик с многоуровневой системой шифрования, напичканной антиотладочными приёмами исполняемого файла, считывающий с компьютера конфиденциальную информацию и передающий её в сеть по закрытому протоколу.
  •  Как и любая сеть, работающая по принципу P2P, Skype подвержен вирусным эпидемиям. Уже известны случаи распространения вредоносных программ, перехватывающих и записывающих разговоры в Skype.

iChat (http://www.apple.com/macosx/what-is-macosx/ichat.html)

iChat (последняя версия 3.19.0.111, страна-производитель: США, компания Apple, 2010г.) — программа для мгновенного обмена сообщениями, представлена компанией Apple Inc. Специфика данной программы в том, что она разработана под платформу Macintosh. В новой версии добавлены функции голосового и видео чата. Входит в стандартную поставку Mac OS X.

Возможности: Текстовый чат, аудиочат, видеочат, удалённый доступ к рабочему столу, удалённая демонстрация документов (iChat Theater), везде поддерживаются конференции с более чем двумя собеседниками.

Поддерживаемые протоколы: OSCAR (AIM, ICQ), XMPP (Jabber), Bonjour LAN Chat.

Минусы:

  •  Поддерживает только платформу Macintosh.


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

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

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

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

Эту задачу решает дейтаграммный протокол UDP, задача которого – быстрая доставка дейтаграмм без установления соединения, повторной передачи и гарантии доставки пакета. Несмотря на эти недостатки, протокол UDP более предпочтителен для передачи данных реального времени, так как обеспечивает более быструю передачу данных.

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

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

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

  •  Разработка  протокола общения  сервера  с клиентом;
  •  Разработка  программного  комплекса, состоящего  из приложения клиента и приложения сервера, которые будут использовать  данный протокол. При этом необходимо использовать аутентификацию клиентов на сервере;
  •  Организация аудиосвязи между клиентами;


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

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

Для сетевого взаимодействия применяется гибридная архитектура.

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

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

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

С другой стороны необходимо обеспечить быстрое и эффективное взаимодействие между клиентами для передачи мультимедиа. Поэтому была реализована архитектура «точка-точка», схема которой представлена на рисунке 2.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. Технологическая часть

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.3.1. Описание модулей серверного приложения

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

  1.   Автоматический поиск IP-адресов, на которых может быть запущен сервер;
  2.   Запуск сервера;
  3.   Остановка сервера;
  4.   Журналирование. Используется файл serverLog.txt;
  5.   Просмотр и удаление файла журнала. 

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

  1.  Подключение к серверу;
  2.  Отключение от сервера;
  3.  Подключение к пользователю;
  4.  Отключение от пользователя;
  5.  Передача аудио-данных от пользователя к пользователю;
  6.  Уведомления  о  произошедших  ошибках,  возникших  в  процессе работы. Они реализованы в виде всплывающих окон.


Заключение

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

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

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

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

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

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

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

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

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


Список использованной литературы

  1.  Библиотека MSDN [Электронный ресурс] , 2011. – Режим доступа

http://msdn.microsoft.com/ru-ru/library

  1.  Таненбаум Э. Компьютерные сети. – СПб.: Питер, 2003. – 992 с.
  2.  Википедия – Свободная энциклопедия – http://ru.wikipedia.org/, 2011
  3.  Эндрю Кровчик, Винод Кумар, Номан Лагари и др. .NET Сетевое программирование для профессионалов. Издательство «ЛОРИ», 2005. – 400стр.


Приложения

Клиент:
using System;
using System.Collections.Generic;
using System.Linq;

using System.Text;

using System.Net;

using System.Net.Sockets;

using System.Threading;

using System.Windows.Forms;

namespace Client

{

   public delegate void NeedListRedraw();

   public delegate void EmptyHandler();

   class Client

   {

       frmClient form;

       String nickName;

       String password;

       Socket socket;

       Thread mainThread;

       public String connectedUser = "";

       public List<String> connectedUsers;

       AudioTransceiver audiotransceiver;

       bool isTransfering;

       public 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>();

       }

       public String GetUserName()

       {

           return nickName;

       }

       public void Connect(String hostName)

       {

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

           socket.Connect(hostName, 11000);

           int port = ((IPEndPoint)socket.LocalEndPoint).Port - 1000;

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

           audiotransceiver = new AudioTransceiver(ipAddress, port);

           byte 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);

           audiotransceiver.AudioEndHandler = new EmptyHandler(AudioEnd);

           mainThread = 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 { }

       }

       void 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;

                           }

                   }

               }

           }

           catch (ThreadAbortException e)

           {

           }

           catch (Exception e)

           {

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

               Stop();

           }

       }

       void 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);

           }

       }

       void ConnectToClientSuccess()

       {

           User user = SocketReader.ReadUserRecord(socket);

           audiotransceiver.Connect(user.ipEndPoint);

           audiotransceiver.BeginTransceiving();

           connectedUser = user.nickName;

       }

       void ConnectToClientFailed()

       {

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

       }

       public void DisconnectAudio()

       {

           try

           {

               if (audiotransceiver != null)

               {

                   audiotransceiver.EndTransceiving();

                   //audiotransceiver.Dispose();

               }

           }

           catch

           {

           }

          // }

       }

       void 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 = "";

       }

   }

}

Сервер:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net;

using System.Net.Sockets;

using System.Threading;

using System.Windows.Forms;

namespace 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;

       public 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;

       }

       public 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());

       }

       public void Stop()

       {

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

           foreach (Connection connection in connections)

               SendMessage(connection, Messages.ServerClose);

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

           connections.Clear();

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

           socket.Close();

           mainThread.Abort();

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

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

       }

       private void MainThread()

       {

           try

           {

               while (true)

               {

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

                   Socket connectionSocket = socket.Accept();

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

                   Connection connection = new Connection();

                   connection.socket = connectionSocket;

                   logWriter.WriteToLogFile("Новое соединение. " +

connectionSocket.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();

           }

       }

       private 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;

                           }

                   }

               }

           }

           catch (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("Запрос на подключение от пользователя " +

connection.userNickName + " пользователю " + requestedUser.nickName);

           foreach (Connection _connection in connections)

           {

               if (_connection.userNickName == requestedUser.nickName)

               {

                   SendMessage(_connection, Messages.ConnectToClientRequest);

                   //SocketWriter.WriteString(_connection.socket,

connection.userNickName);

                   SocketWriter.WriteUserRecord(_connection.socket,

connection.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,

connection.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;

               }

           }

       }

       private void DisconnectRequest(Connection connection)

       {

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

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

connection.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);

               }

           }

           return 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);

       }

       private void SendMessage(Connection connection, Messages messageType)

       {

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

       }

   }

}


 

А также другие работы, которые могут Вас заинтересовать

29105. Общая совместная собственность 26.5 KB
  Общая совместная собственность Доля участника совместной собственности в общем имуществе заранее не определена. Она устанавливается при разделе между участниками совместной собственности а также при выделе доли одного из них. Особенности: Доли не выявлены но предполагаются равными Владение пользование и распоряжение осуществляется при согласии в случае спора – в суд Режим общей совместной собственности всеми проживающими в жилом помещении вне зависимости от родства и свойства. Виды совместной собственности: – общая собственность супругов...
29106. Долевая собственность. Преимущественное право покупки доли 35.5 KB
  Преимущественное право покупки доли. Доли в праве долевой собственности могут быть: Равными Неравными Размер доли может быть изменен при осуществление неотделимых улучшений Долевая собственность может возникать: закону договору в порядке наследования в силу приобретательной давности. Особенности содержания: владение и пользование – по соглашению участников по решению суда в случае спора распоряжение по соглашению участников при отсутствие согласия с обязательным учетом на право преимущественной покупки При продаже доли...
29108. Виндикационный иск 29.5 KB
  При этом субъектом права на виндикацию является собственник законный владелец который должен доказать свое право на истребуемое имущество. Имущество у добросовестного приобретателя можно истребовать: в случае если такое имущество было им получено безвозмездно дарение наследование и т. При этом такое изъятие не несет имущественных убытков добросовестному приобретателю но способствует восстановлению нарушенного права собственности; в случае возмездного приобретения имущества добросовестным приобретателем у лица которое не имело права...
29109. Негаторный иск 21 KB
  Субъектом негаторного иска является собственник или владелец сохраняющий вещь в своем владении но испытывающий препятствия в ее использовании. Объект требований по негаторному иску составляет устранение длящегося правонарушения противоправного состояния сохраняющегося к моменту предъявления иска. Поэтому к подобного рода искам не применяется срок исковой давности – требование можно предъявить в любой момент пока сохраняется правонарушение.
29110. Классификация и сущность способов защиты гражданских прав 28.5 KB
  В зависимости от характера посягательства на права собственника и содержания предоставляемой защиты можно выделить обязательственноправовые вещноправовые иные способы защиты. Обязательноправовые способы защиты права собственности основаны на охране имущественных интересов сторон в гражданской сделке а также лиц которые понесли ущерб в результате внедоговорного причинения вреда их имуществу. Вещноправовые способы защиты права собственности направлены на устранение препятствий к осуществлению права собственности. Негаторный иск это...
29111. Понятие и виды гражданско-правовой ответственности (особенности, функции, гражданско-правовые санкции, классификация, основания и условия ответственности) 37.5 KB
  Понятие и виды гражданскоправовой ответственности особенности функции гражданскоправовые санкции классификация основания и условия ответственности. Гражданская ответственность вид юридической ответственности; установленные нормами гражданского права юридические последствия неисполнения или ненадлежащего исполнения лицом предусмотренных гражданским правом обязанностей что связано с нарушением субъективных гражданских прав другого лица. Классификация: от основания возникновения ответственности: договорную ответственность в случаях...
29112. Понятие и виды гражданско-правовых обязательств 29 KB
  Понятие и виды гражданскоправовых обязательств. Под обязательством понимается гражданское правоотношение в силу которого одно лицо должник обязано совершить в пользу другого лица кредитора определенное действие передать имущество выполнить работу уплатить деньги либо воздержаться от определенного действия а кредитор имеет право требовать от должника исполнения его обязанности. Виды: Встречные – возникают только в случае взаимного обязательства; Простые договор займа и сложные договор куплипродажи Альтернативные и...
29113. Принципы исполнения обязательств 25 KB
  Исполнение обязательств выражающееся в совершении или в воздержании от действий составляющих предмет обязательства базируется на ряде принципов. Принцип надлежащего исполнения обязательства должны исполняться надлежащим образом в соответствии с условиями обязательства и требованиями закона иных правовых актов а при их отсутствии – в соответствии с обычаями делового оборота или иными обычно предъявляемыми требованиями надлежащему лицу в день или период времени предусмотренный обязательством в установленном месте. Принцип...