Файл: Разработка системы мгновенного обмена сообщениями.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 25.04.2024

Просмотров: 31

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

5. Отправка Файла:

  • Клиент посылает на сервер строку ‘#F имя файла’

  • сервер создаёт файл с именем ‘имя файла’.

  • Клиент посылает файл.

  • Клиент посылает строку ‘#S имя файла’’, что означает что клиент хочет отправить файл c именем ‘имя файла’, который уже находится на сервере всем остальным клиентам.

  • Сервер рассылает всем подключенным клиентам строку ‘#F имя файла’.

  • Клиенты создают файл.

  • Сервер посылает файл.

Раздел 2. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ



Для реализации программ используется интегрированная среда разработки Visual Studio и её стандартные компоненты. Система программирования Visual Studio рассчитана на программирование различных приложений и предоставляет большое количество компонентов для этого. К тому же работодателей интересует, прежде всего, скорость и качество создания программ, а эти характеристики может обеспечить только среда визуального проектирования, способная взять на себя значительные объемы рутинной работы по подготовке приложений. Возможности Visual Studio полностью отвечают подобным требованиям и подходят для создания системы обмена мгновенными сообщениями.

2.1 Используемые компоненты



Как уже было сказано выше все используемые компоненты идут в стандартной версии Visual Studio 2019, но не все они по умолчанию доступны. Основные компоненты которые будут отвечать за передачу данных по сети, нужно включить, чтобы это сделать следует проделать следующие действия:

  • Запустить Visual Studio.

  • На верхней панели выбрать вкладку Component => Install Packages => Add

  • Найти файл «dclsockets7. bpl» в папке bin c установленной Visual Studio

  • Теперь нужные компоненты будут доступны в программе.

Используемые компоненты для реализации сетевого взаимодействия:

  • TServerSocket \\Компонент серверной части

  • TClientSocket \\Компонент клиентской части

Эта пара компонентов ServerSocket и ClientSocket нужны для работы программ по сети. По моему личному мнению эти компоненты куда лучше подходят для реализации данной работы, они являются более простыми для освоения, хотя эти компоненты и не являются рекомендуемыми я считаю что изучать сетевое взаимодействие в Visual Studio нужно именно с них, и так как я являюсь новичком в этой области программирования, то эти компоненты как никак кстати подойдут для начала освоения программирования сетевых программ и взаимодействия в сети.


2.2 Описание свойств и методов




Описание TServerSocket.

Свойства

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

Тип: TServerWinSocket; ServerType – тип сервера. Может принимать одно из двух значений: stNonBlocking – синхронная работа с клиентскими сокетами. При таком типе сервера можно работать с клиентами через события OnClientRead и OnClientWrite.

stThreadBlocking – асинхронный тип. Для каждого клиентского сокетного канала создается отдельный процесс (Thread).

Тип: TServerType; ThreadCacheSize – количество клиентских процессов (Thread), которые будут кэшироваться сервером. Здесь необходимо подбирать среднее значение в зависимости от загруженности Вашего сервера. Кэширование происходит для того, чтобы не создавать каждый раз отдельный процесс и не убивать закрытый сокет, а оставить их для дальнейшего использования.

Тип: Integer; Active – показатель того, активен в данных момент сервер, или нет. Т.е., фактически, значение True указывает на то, что сервер работает и готов к приему клиентов, а False – сервер выключен. Чтобы запустить сервер, нужно просто присвоить этому свойству значение True.

Тип: Boolean; Port – номер порта для установления соединений с клиентами. Порт у сервера и у клиентов должны быть одинаковыми. Рекомендуются значения от 1025 до 65535, т.к. от 1 до 1024 – могут быть заняты системой.

Тип: Integer; Service – строка, определяющая службу (ftp, http, pop, и т.д.), порт которой будет использован. Это своеобразный справочник соответствия номеров портов различным стандартным протоколам.

Методы

Open – Запускает сервер. По сути, эта команда идентична присвоению значенияTrue свойству Active;

Close – Останавливает сервер. По сути, эта команда идентична присвоению значенияFalse свойству Active.

События

OnClientConnect – возникает, когда клиент установил сокетное соединение и ждет ответа сервера (OnAccept);

OnClientDisconnect – возникает, когда клиент отсоединился от сокетного канала;

OnClientError – возникает, когда текущая операция завершилась неудачно, т.е. произошла ошибка;

OnClientRead – возникает, когда клиент передал берверу какие–либо данные. Доступ к этим данным можно получить через пеаедаваемый параметр Socket: TCustomWinSocket;

OnClientWrite – возникает, когда сервер может отправлять данные клиенту по сокету;

OnGetSocket – в обработчике этого события Вы можете отредактировать параметр ClientSocket;

OnGetThread – в обработчике этого события Вы можете определить уникальный процесс (Thread) для каждого отдельного клиентского канала, присвоив параметру SocketThread нужную подзадачу TServerClientThread;


OnThreadStart, OnThreadEnd – возникает, когда подзадача (процесс, Thread) запускается или останавливается, соответственно;

OnAccept – возникает, когда сервер принимает клиента или отказывает ему в соединении;

OnListen – возникает, когда сервер переходит в режим ожидания подсоединения клиентов.
Описание TClientSocket.

Свойства

Active – показывает, открыт сокет или нет.

Тип: Boolean. Соответственно, True – открыт, а False – закрыт. Это свойство доступно для записи; Host – строка (Тип: string), указывающая на хост–имя компьютера, к которому следует подключиться;

Address – строка (Тип: string), указывающая на IP–адрес компьютера, к которому следует подключиться. В отличие от Host, здесь может содержаться лишь IP. Отличие в том, что если указать в Host символьное имя компьютера, то IP адрес, соответствующий этому имени будет запрошен у DNS;

Port – номер порта (Тип: Integer (Word)), к которому следует подключиться. Допустимые значения – от 1 до 65535;

Service – строка (Тип: string), определяющая службу (ftp, http, pop, и т.д.), к порту которой произойдет подключение. Это своеобразный справочник соответствия номеров портов различным стандартным протоколам;

ClientType – тип соединения.

ctNonBlocking – асинхронная передача данных, т.е. посылать и принимать данные по сокету можно одновременно с помощью OnRead и OnWrite;

ctBlocking – синхронная передача данных. События OnRead и OnWrite не работают. Этот тип соединения полезен для организации обмена данными с помощью потоков (т.е. работа с сокетом как с файлом).

Методы

Open – открытие сокета (аналогично присвоению значения True свойству Active);

Close – закрытие сокета (аналогично присвоению значения False свойству Active).

События

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

OnConnecting – возникает при установлении соединения. Отличие от OnConnect в том, что соединение еще не установлено. Обычно такие промежуточные события используются для обновления статуса;

OnDisconnect – возникает при закрытии сокета. Причем, закрытия как из Вашей программы, так и со строноны удаленного компьютера (либо из–за сбоя);

OnError – продолжает грустную тему предыдущего события:). Возникает при ошибке в работе сокета. Следует отметить, что это событие не поможет отловить ошибку в момент открытия сокета (Open). Для того, чтобы избежать выдачи виндозного сообщения об ошибке, надо заключить операторы открытия сокета в блок try. except (обработка исключительных ситуаций);


OnLookup – возникает при попытке получения от DNS IP–адреса указанного хоста;

OnRead – возникает, когда удаленный компьютер послал Вам какие–либо данные. При возникновении этого события возможна обработка данных;

OnWrite – возникает, когда разрешена запись данных в сокет.

2.3 Исходный код Сервера отвечающий за сетевое взаимодействие



// К серверу подключился клиент (OnClientConnect)

var i: Integer;

{Кто-то присоединился или отсоединился? Запрашиваем у всех

юзеров их имена}. Items. Clear;i: = 0 to ServerSocket1. Socket. ActiveConnections-1 do. Socket. Connections [i]. SendText ('#N');. Lines. Add (timetostr (now) +': '+'Пользователь подключился. В сети: '+inttostr (ServerSocket1. Socket. ActiveConnections));

// От сервера отключился клиент (OnClientDisconnect)

var i: Integer;

{Кто-то присоединился или отсоединился? Нет проблем! Запрашиваем у всех юзеров их имена}. Items. Clear;i: = 0 to ServerSocket1. Socket. ActiveConnections-1 do. Socket. Connections [i]. SendText ('#N');. Lines. Add (timetostr (now) +': '+'Пользователь отключился. В сети: '+inttostr (ServerSocket1. Socket. ActiveConnections));

// Сервер получает данные от клиента (OnClientRead)

var s,s1: string;: Integer;: Integer;: Pointer;: string;: string;

{сохраняем в s присланную нам строку}: = Socket. ReceiveText;

{Если кто-то шлёт файл}Copy (s,1,2) = '#F' then(s,1,2);: =s;

{Процедура создания файла}_create (filename);;;

{Кто-то хочет переслать всем файл}Copy (s,1,2) = '#S' then(s,1,2);. Destroy;i: = 0 to ServerSocket1. Socket. ActiveConnections-1 do. Socket. Connections [i]. SendText ('#F'+s);. Socket. Connections [i]. SendStream (TFileStream. Create ('temp/'+s, fmOpenReadWrite or fmShareDenyWrite));;;;

{кто-то шлёт своё имя}Copy (s,1,2) = '#N' then(s,1,2);

{Добавляем его в юзер лист}. Items. Add (s);

{Записываем в s команду для посылки нового списка юзеров}: = '#U';i: = 0 to ListBox1. Items. Count-1 do: = s+ListBox1. Items [i] +'; ';

{. и рассылаем этот список всем клиентам}i: = 0 to ServerSocket1. Socket. ActiveConnections-1 do. Socket. Connections [i]. SendText (s);;;

{Если кто-то кинул сообщение - рассылаем его всем клиентам}(Copy (s,1,2) = '#M') or (Copy (s,1,2) = '#P') then begini: = 0 to ServerSocket1. Socket. ActiveConnections-1 do. Socket. Connections [i]. SendText (s);;;;

// Получение файла (Файловый сервер)

var s,s1: string;: Integer;: Integer;: Pointer;: = Socket. ReceiveLength;(Bfr, iLen);. ReceiveBuf (Bfr^, iLen);. Write (Bfr^, iLen);(Bfr);;;.


2.4 Исходный код Клиента отвечающий за сетевое взаимодействие



// Кнопка подключения к серверу

var,port: string;

{Проверка введены ли данные (ip,port,nickname) }(edit2. Text='') or (edit3. Text='') or (edit4. Text='') then. Panels [0]. Text: ='Заполните все поля'

{Если уже есть подключение}ClientSocket1. Active then: =edit2. Text;: =edit3. Text;: =edit4. Text;. Host: =host;. port: =strtoint (port);. Open;. Host: =ClientSocket1. host;. port: =ClientSocket1. port+50;. Open;

{Если нет подключение}. Close;. Close;: =edit2. Text;: =edit3. Text;: =edit4. Text;. Host: = host;. Port: = StrToInt (port);: =edit4. Text;. Open;. Host: =ClientSocket1. host;. port: =ClientSocket1. port+50;. Open;;;

// Кнопка отключения от сервера

Begin


{Закрытие подключения}. Close;. Close;;

// Команды от сервера

var s,from_,to_: string;: integer;

{присваиваем s полученную от сервера строку}: = Socket. ReceiveText;Copy (s,1,2) = '#F' then(s,1,2);: = TFileStream. Create ('temp\'+s, fmCreate or fmShareDenyWrite);;;

{Если сервер посылает нам Новый Ник}Copy (s,1,2) = '#K' then begin(s,1,2);copy (s,1,pos ('; ',s) - 1) =NickName then begin(s,1,pos ('; ',s));('Администратор изменил ваше имя на: - '+S);. Text: =S;. Click;. Click;;;;;

{Если сервер посылает нам User List}Copy (s,1,2) = '#U' then begin(s,1,2);: =0;

{Чистим ListBox1}. Items. Clear;

{Добавляем по одному юзеру в список. Имена юзеров разделены знаком «; «}Pos ('; ',s) > 0 do begin. Items. Add (Copy (s,1,Pos ('; ',s) - 1));(s,1,Pos ('; ',s));;;;

{Если нам прислали общее сообщение (видимое для всех юзеров) }Copy (s,1,2) = '#M' then begin(s,1,2);

{Добавляем его в Memo1}. Lines. Insert (0,Copy (s,1,Pos ('; ',s) - 1) +'> '+ Copy (s,Pos ('; ',s) +1,Length (s) - Pos ('; ',s)));;;

{Если нам прислали запрос на наше имя юзера}Copy (s,1,2) = '#N' then begin

{Посылаем ответ}. SendText ('#N'+nickname);;;

{Если нам прислали приватное сообщение (или не нам:)) }Copy (s,1,2) = '#P' then begin(s,1,2);

{Выделяем в to_ - кому оно предназначено}_: = Copy (s,1,Pos ('; ',s) - 1);(s,1,Pos ('; ',s));

{Выделяем в from_ - кем отправлено}_: = Copy (s,1,Pos ('; ',s) - 1);(s,1,Pos ('; ',s));

{Если оно для нас, или написано нами - добавляем в Memo1

(иногда полезно убрать этот оператор if:)) }(to_ = nickname) or (from_ = nickname) then. Lines. Insert (0,from_+' (private) > '+s);. SelStart: =0;. SelLength: =RichEdit1. Lines [1]. Length;. selAttributes. Color: = clred;;;;Copy (s,1,2) = '#D' then begin(s,1,2);s=nickname then begin. Click;('Вы отключены Администратором');;;;Copy (s,1,2) = '#A' then begin(s,1,2);copy (s,1,pos ('; ',s) - 1) =NickName then begin(s,1,pos ('; ',s));('Администратор: - '+S);;;;;;

// Получение файла

var s,s1: string;: Integer;: Integer;: Pointer;: = Socket. ReceiveLength;(Bfr, iLen);. ReceiveBuf (Bfr^, iLen);. Write (Bfr^, iLen);(Bfr);;;

// Отправка сообщения

var s: string;(CheckBox1. Checked) and (ListBox1. ItemIndex < 0) then begin('Чтобы послать приватное сообшение, сначала выберите получателя! ');;;

{Если это приватное сообщение}CheckBox1. Checked=true then: = '#P'+ListBox1. Items [ListBox1. ItemIndex] +'; ' {добавляем спец. команду и адресат}{А если не очень приватное? }: = '#M'; {Просто спец. команду}

{Добавляем наше имя (от кого) и само сообщение}: = s+nickname+'; '+Edit1. Text;

{Посылаем все это добро по сокету}. Socket. SendText (s);

{И снова ждем ввода в уже чистом TEdit-е}. Text: = '';: = Edit1;;

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

begin. Free;. Execute;. Socket. SendText ('#F'+ExtractFileName (opendialog1. FileName));. Socket. SendStream (TFileStream. Create (opendialog1. FileName, fmOpenReadWrite or fmShareDenyWrite));. Socket. SendText ('#S'+ExtractFileName (opendialog1. FileName));. Free;

2.5 Порядок работы с программой



Работа с сервером


Рисунок 1 – Настройки сервера
Настройки сервера. Главной настройкой является поле «Порт» по умолчанию стоит порт «1010». Сервер можно запустить нажав на кнопку «Запуск», если порт свободен и нет больше никаких проблем то в строке состояния отобразится надпись «Сервер запушен», теперь клиенты могут подключаться к серверу. Отключение сервера происходит нажатием кнопкой «Отключить». Есть возможность свернуть сервер в трэй, нажатием кнопки «Свернуть в трэй».