РефератыИнформатика, программированиеПрПроектирование и разработка программы ЧАТ для локальной сети

Проектирование и разработка программы ЧАТ для локальной сети

АВТОНОМНАЯ НЕКОМЕРЧЕСКАЯ ОБРАЗОВАТЕЛЬНАЯ ОРГАНИЗАЦИЯВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯВОРОНЕЖСКИЙ ЭКОНОМИКО-ПРАВОВОЙ ИНСТИТУТ


ФИЛИАЛ г.СТАРЫЙ ОСКОЛ БЕЛГОРОДСКОЙ ОБЛАСТИ


ЭКОНОМИЧЧЕСКИЙ ФАКУЛЬТЕТ


КАФЕДРА «ГУМАНИТАРНЫХ И ЕСТЕСТВЕННОНАУЧНЫХ ДИСЦИПЛИН»


Курсовая работа


По дисциплине: Проектирование информационных систем


На тему


Проектирование и разработка программы ЧАТ для локальной сети


Выполнил


Кирилов О.И.


Содержание


Введение


Глава I. История возникновения чата


Виды чатов


Глава II. Создание многопользовательского чата


Листинг программы


Заключение


Приложение


Введение


Работая в сети Internet, мы очень часто встречаемся с разного рода многопользовательскими программами. Ими могут быть почтовые клиенты, чаты, форумы, FTP клиенты и т.п. Все эти приложения используют для своей работы разного рода протокола: FTP, POP, SMTP, HTTP, и т.д. Но базовым для них является единый протокол - TCP/IP. Типичное же приложение TCP/IP построено на клиент-серверной архитектуре. Примером приложения построенного на данной архитектуре, является чат реального времени. В данной курсовой работе я буду создавать чат средствами Borland Delphi. Для этой цели мне необходимы компоненты TClientSocket и TServerSocket Выбранные компоненты при работе с протоколом TCP/IP используют интерфейс сокетов. Но прежде чем перейти к разработке чата, разберем, что же такое сокеты.

Сокеты – это интерфейс прикладного программирования для сетевых приложений TCP/IP. Интерфейс сокетов был создан в восьмидесятых годах для операционной системы UNIX. Позднее интерфейс сокетов был перенесен в MicrosoftWindows. Сокеты до сих пор используются в приложениях для сетей TCP/IP. В переводе с английского "sockets" – гнезда, т.е. сетевые приложения используют сокеты, как виртуальные разъемы для обмена данными между собой. Сокеты бывают трех видов: клиентские, слушающие и серверные. Клиентские сокеты устанавливают связь с сервером и обмениваются с ним данными. Клиентский сокет включен в компонент TClientSocket. Слушающий сокет принимает запрос на соединение от клиентского сокета, и соединяет сервер с клиентом. Слушающий сокет содержится в компоненте TServerSocket. Серверный сокет обменивается данными с клиентом по уже установленному (слушающим сокетом) соединению. Для того чтобы клиент мог установить соединение с сервером, ему необходимо указать его адрес (IP) и номер порта, через который будет происходить обмен данными.


Глава
I
. История возникновения чата


Вопросы общения интересовали людей всегда. Для того, чтобы можно было обмениваться информацией не только при личной встрече, но и на огромных расстояниях, люди изобретали всё новые и новые технические средства, организовывали почтовые системы, протягивали кабели через континенты и океаны, запускали спутники связи. С развитием информационных технологий стали возможным еще более глобальные коммуникации. Историческим «докомпьютерным» предшественником чатов, несомненно, был телефон. Ни почта, ни телеграф не позволяли общаться в реальном времени и не были доступны в домашней обстановке. Изобретение и распространение телефона по планете вызвало настоящую революцию в средствах и способах общения. Возможность поговорить с собеседником на другой стороне Земли казалась настоящим чудом.


Во второй половине XX века начали бурно развиваться компьютеры. Однако долгое время они были большими и слишком дорогими, что препятствовало тому, чтобы расходовать драгоценное машинное время на забавы с обменом сообщениями вместо расчетов атомных бомб. К тому же, до конца 60-х годов они не были связаны друг с другом. Предок Интернета, сеть ARPANET, в 1969 году насчитывала только четыре связанных друг с другом научных компьютера. Чуть позже, в 1971 году, была придумана электронная почта, которая стала необычайно популярна ввиду своего удобства. Постепенно появились новые службы сообщений, такие, как списки почтовой рассылки, новостные группы и доски объявлений. Однако в то время сеть ARPANET ещё не могла легко взаимодействовать с другими сетями, построенными на других технических стандартах, что затрудняло её распространение. Но тем не менее, эта проблема вскоре была решена после перехода сетей на протокол обмена данными TCP/IP, который успешно применяется до сих пор. Именно в 1983 году термин «Интернет» закрепился за сетью ARPANET.


Программы для обмена текстовыми строками, несмотря на простоту самой идеи, появились не сразу. Примерно в 1974 году для мэйнфрейма PLATO был разработана программа Talkomatic, потенциально позволявшая общаться между тысячей терминалов системы. В 1980-x появилась система Freelancing' Round table. Однако по-настоящему популярным стал разработанный в 1988 году протокол, названный Internet Relay Chat (IRC), что примерно можно перевести как ретранслируемый интернет-разговор. Где-то в это же время появилось и распространилось само понятие «чат». Общение в IRC быстро стало популярным из-за простоты процесса и дружественности среды. В 1991 году во время операции «Буря в пустыне» была организована IRC-трансляция новостей — сообщения со всего мира собирались в одном месте и в режиме реального времени передавались в IRC. Есть сведения, что подобным образом IRC использовался и во время путча в СССР, когда пользователи из Москвы моментально сообщали всему миру о происходящем на улицах. Для клиентов IRC, написано множество ботов, например, Eggdrop, автоматизирующие многие рутинные операции. Самым известным из клиентов IRC стал mIRC; благодаря простой и эффективной системе команд для него было написано множество скриптов, которые также позволяют выполнять широкий спектр действий. Боты и mIRC-боты используются для различных игр в каналах — «Мафия», «Викторина», и других. Разработчики IRC настолько хорошо продумали его архитектуру, что её с тех пор практически не требовалось изменять. Конечно, у него есть недостатки: короткие сообщения, проблема с кодировками, невозможность посмотреть историю сообщений при подключении. Однако он был и остаётся популярным средством для чата, хотя и в значительной мере потеснен со своих позиций. В частности, в 1998 году был придуман похожего назначения протокол Jabber - даже его название (англ. jabber болтовня, трёп; тарабарщина) отсылало к слову chat. Jabber содержал в себе многие технические новшества и постепенно получил широкое распространение, а также стал основой многих сервисов. Были и другие протоколы, менее известные, например, SIP.


Виды чатов


Существует несколько разновидностей программной реализации чатов:


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


IRC, специализированный протокол для чатов.


Программы-чаты для общения в локальных сетях (например, Vypress Chat, Intranet Chat). Часто есть возможность передачи файлов.


Чаты, реализованные поверх сторонних протоколов (например чат, использующий ICQ).


По применению чаты делятся на:


all2all - групповая коммуникация (например, IRC, Jabber, Yahoo! Chat, AVACS Live Chat);


p2p - персональные коммуникации (например, ICQ, Jabber, Skype, Yahoo! Messenger, AOLInstantMessenger, Hamachi) — личное общение.


Глава
II
. Создание многопользовательского чата (
Multy
-
user
on
-
line
)


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


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


PortEdit (Edit)


HostEdit (Edit)


NikEdit (Edit)


TextEdit (Edit)


ChatMemo (Memo)


ClientBtn (Button)


ServerBtn (Button)


SendBtn (Button)


ServerSocket (ServerSocket)


ClientSocket (ClientSocket)


UserListView (ListView)


ImageList (ImageList)


ServerTimer (Timer)


Компонентыизстандартногопакета Delphi ServerSocket и ClientSocket невсегдамогутбытьотображенывпалитре Internet, иихнужнозагрузитьследующимобразом: выбратьменю: Component - Install Packages… - Add., далеенужноуказатьфайл …bindclsockets70.bpl.


Как правило, разработка любой программы начинается с определения задач, которые она должна выполнять, и определения уже на этом этапе нужных компонентов. Программа представляет собой чат для нескольких пользователей, каждый из которых может быть как сервером, так и клиентом, значит, кидаем в форму компоненты ServerSocket и ClientSocket. Важным параметром для всех является порт. Только при одинаковом значении свойства Port, связь между ними установится. Кинем в форму компонент Edit, чтобы оперативно изменять порт, назовем его PortEdit. Для соединения с сервером необходимо указывать IP сервера или его имя, поэтому кинем еще один Edit, назовем его HostEdit. Так же нам понадобятся еще два Edit’а для указания ника и ввода текста сообщения, назовем их NikEdit и TextEdit, соответственно. Текст принимаемых и отправляемых сообщений будет отображаться в Memo, кинем его в форму и назовем ChatMemo. Установим сразу вертикальную полосу прокрутки: ScrollBars = ssVertical, и свойство ReadOnly = True. Добавим клавиши управления Button: ServerBtn – для создания/закрытия сервера, ClientBtn – для подключения/отключения клиента к серверу, SendBtn - для отправки сообщений. Изменим Caption этих клавиш на “Создать сервер”, “Подключиться” и “Отправить”, соответственно. UserListView предназначен для вывода списка пользователей, который будет динамически обновляться при подключении или отключении пользователей. Сам компонент ListView настраивается как табличный отчет: свойство ViewStyle = vsReport (стиль таблицы), свойство ShowColumnHeaders = False (не показывать имена столбцов), свойство ReadOnly = True (только отображение), свойство SmallImages = ImageList (массив с иконками). Двойным кликом на компоненте ListView выводится редактор Editing UserListView.Columns. Добавляется один столбец (порядковый номер -0). В ImageList через Add закидываются иконки, в нашем случае две, с изображением силуэта пользователя: в белом – пометка сервера, в красном – пометка клиента.


Теперь разберем принцип работы сервера
. Традиционно в ServerSocket для приема клиентских пакетов используется OnClientRead, но данный способ не очень удобен, ведь для идентификации пакета (кто прислал) потребуется повозиться со структурой “приемответ” и решить каким образом будет происходить синхронизация. Гораздо проще и эффективнее использовать цикл по числу пользователей, в котором ведется “прослушивание” всех каналов и обработка пакета, если он пришел на конкретный канал, закрепленный за конкретным пользователем. Процедура “прослушивания” каналов выполняется в теле таймера, интервал (Interval) работы которого можно изменять по необходимости (для чата нормально 500 мс, для игр нужно существенно меньше). Вот так выглядит общая структура процедуры опроса:


procedure TForm1.Timer1Timer(Sender: TObject);


begin// условие на наличие установленных каналов


if ServerSocket.Socket.ActiveConnections<>0 then begin // циклпосуществующимканалам


for i:=1 to ServerSocket.Socket.ActiveConnections do begin // сохранимпакет (еслиничегонеприслали, попакетпустой)


text:=ServerSocket.Socket.Connections.ReceiveText(); // условие, что пакет не пуст iftext<>” thenbegin{тут обработка строки, выделение составляющих кода команд (com) и пр.} // определение команд casecomofкод: begin{процедура} end; код: begin{процедура} end; ……………………………………. end; end; end; end; // разрешение на выполнение процедур обновления ifUpdDo=Truethenbegin{процедуры} // блокируем разрешение UpdDo:=False; end; end;


Если заметили, что цикл начинается с единицы, а в инициализации канала странное выражение (вместо логичного начала с нуля и инициализации), то такое решение существенным образом облегчает организацию ряда процедур. Например, в списке пользователей, сервер числится под номером “0”, а клиенты - начиная с “1”. Так же удобно совмещать количество каналов (ServerSocket.Socket.ActiveConnections) с процедурами определения активности пользователей. Последнее условие в теле таймера необходимо для задержки выполнения некоторых процедур обновления. Эти процедуры должны выполняться в самом конце “прослушивания” открытых каналов, и не всегда (если будет команда). Данный алгоритм применим практически к любого рода соединениям Клиент-сервер, в том числе и для игр.


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


Type TUserList = object Status: Byte; // 1 - сервер, 2 - клиент Rec: Boolean; // отметка записи пользователя в список Name: String; // имя (ник) Image: Byte; // индекс иконки end;


Вот переменные, которые понадобятся в программе:


var Form1: TForm1; i, j, com, ContList: Byte; len, pos, x: Word; text, StrUserList: String; UpdDo: Boolean; Buf: array[0..3] of Byte; UserMas: array[0..255] of TUserList; //массивобъектовUItems: TListItem;


Опишемпроцедуру
OnCreate
формы:


procedure TForm1.FormCreate(Sender: TObject); begin // заголовокформыCaption:='Многопользовательскийчат'; Application.Title:=Caption; // предложенноезначенияпортаPortEdit.Text:='Портсервера'; // адресприпроверкепрограммынаодномПК ("самнасебя") HostEdit.Text:='Адрессервера '; // введемникпо-умолчанию, остальныеполяпростоочистимNikEdit.Text:='Ананим'; TextEdit.Clear; ChatMemo.Lines.Clear; end;


Процедура

прослушивания

открытых
каналов
сервером
, выглядиттак:procedure TForm1.ServerTimerTimer(Sender: TObject); begin // условиенаналичиеустановленныхканаловif ServerSocket.Socket.ActiveConnections<>0 then begin // циклпосуществующимканаламfor i:=1 to ServerSocket.Socket.ActiveConnections do begin // сохранимпакет (еслиничегонеприслали, попакетпустой)


text:=ServerSocket.Socket.Connections.ReceiveText(); // условие, что пакет не пуст if text<>” then begin // получим код команды, длину строки com:=StrToInt(Copy(text,1,1)); len:=Length(text)-1; // определение команд case com of // код приема сообщения 0: begin // добавим в ChatMemo сообщение клиента ChatMemo.Lines.Add(Copy(text,2,len)); // разошлем сообщение пользователям (кроме того, кто прислал) for j:=0 to ServerSocket.Socket.ActiveConnections-1 do begin if (j+1)<>i then ServerSocket.Socket.Connections[j].SendText(’0′+Copy(text,2,len)); end; end; // код приема ника клиента 1: begin // запишем в массив полученный ник UserMas.Name:=Copy(text,2,len); // отметим, что пользователь записан в список UserMas.Rec:=True; // обновляем список UpdateUserList; end; end; end; end; end; // разрешение на выполнение процедур обновления if UpdDo=True then begin // обновляем массив пользователей UpdateUserMas; // обновляем список пользователей UpdateUserList; // блокируем разрешение UpdDo:=False; end; end;


Перевод программы в режим сервера
осуществляется клавишей “Создать сервер” (ServerBtn). Вот так выглядит процедура на нажатие клавиши ServerBtn (OnClick):


procedure TForm1.ServerBtnClick(Sender: TObject); begin if ServerBtn.Tag=0 then begin // клавишу ClientBtn и поля HostEdit, PortEdit, NikEdit заблокируем ClientBtn.Enabled:=False; HostEdit.Enabled:=False; PortEdit.Enabled:=False; NikEdit.Enabled:=False; // запишем указанный порт в ServerSocket ServerSocket.Port:=StrToInt(PortEdit.Text); // запускаем сервер ServerSocket.Active:=True; // добавим в ChatMemo сообщение с временем создания ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сервер создан.’); // изменяем тэг ServerBtn.Tag:=1; // меняем надпись клавиши ServerBtn.Caption:=’Закрыть сервер’; // включаем таймер сервера ServerTimer.Enabled:=True; // вписываем параметры сервера UserMas[0].Status:=1; UserMas[0].Rec:=True; UserMas[0].Name:=NikEdit.Text; UserMas[0].Image:=1; // разрешаем обновление UpdDo:=True; end else begin // выключаем таймер сервера ServerTimer.Enabled:=False; // стираем параметры сервера UserMas[0].Status:=0; UserMas[0].Rec:=False; UserMas[0].Name:=’Неизвестный’; UserMas[0].Image:=0; // разрешаем обновление UpdDo:=True; // очищаем список клиентов UserListView.Items.Clear; // клавишу ClientBtn и поля HostEdit, PortEdit, NikEdit разблокируем ClientBtn.Enabled:=True; HostEdit.Enabled:=True; PortEdit.Enabled:=True; NikEdit.Enabled:=True; // закрываем сервер ServerSocket.Active:=False; // выводим сообщение в ChatMemo ChatMemo.Lines.Add(’['+TimeToStr(Time)+'] Сервер закрыт.’); // возвращаем тэгу исходное значение ServerBtn.Tag:=0; // возвращаем исходную надпись клавиши ServerBtn.Caption:=’Создать сервер’; end; end;


Далее идут события, которые должны происходить при определенном состоянии ServerSocket’а. Напишем процедуру, когда клиент подсоединился
к серверу (OnClientConnect):


procedure TForm1.ServerSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket); begin // добавим в ChatMemo сообщение с временем подключения клиента ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Подключился клиент.’); // разрешаем обновление UpdDo:=True; end;


Напишем процедуру, когда клиент отключается
(OnClientDisconnect):


procedure TForm1.ServerSocketClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); begin // добавим в ChatMemo сообщение с временем отключения клиента ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Клиент отключился.’); // разрешаем обновление UpdDo:=True; end;


Отправка сообщений
. Она осуществляется нажатием клавиши “Отправить” (SendBtn), но необходима проверка режима программы сервер или клиент. Напишем ее процедуру (OnClick):


procedure TForm1.SendBtnClick(Sender: TObject); begin // проверка, в каком режиме находится программа if ServerSocket.Active=True then // отправляем сообщение с сервера всем пользователям for i:=0 to ServerSocket.Socket.ActiveConnections-1 do ServerSocket.Socket.Connections.SendText(’0['+TimeToStr(Time)+'] ‘+NikEdit.Text+’: ‘+TextEdit.Text) else // отправляем сообщение с клиента ClientSocket.Socket.SendText(’0['+TimeToStr(Time)+'] ‘+NikEdit.Text+’: ‘+TextEdit.Text); // отобразим сообщение в ChatMemo ChatMemo.Lines.Add(’['+TimeToStr(Time)+'] ‘+NikEdit.Text+’: ‘+TextEdit.Text); // очищаем TextEdit TextEdit.Clear; end;


Режим клиента
. При нажатии клавиши “Подключиться” (ClientBtn), блокируется ServerBtn и активируется ClientSocket. Вот процедура ClientBtn (OnClick):


procedure TForm1.ClientBtnClick(Sender: TObject); begin if ClientBtn.Tag=0 then begin // клавишу ServerBtn и поля HostEdit, PortEdit заблокируем ServerBtn.Enabled:=False; HostEdit.Enabled:=False; PortEdit.Enabled:=False; // запишем указанный порт в ClientSocket ClientSocket.Port:=StrToInt(PortEdit.Text); // запишем хост и адрес (одно значение HostEdit в оба) ClientSocket.Host:=HostEdit.Text; ClientSocket.Address:=HostEdit.Text; // запускаем клиента ClientSocket.Active:=True; // изменяем тэг ClientBtn.Tag:=1; // меняем надпись клавиши ClientBtn.Caption:='Отключиться'; end else begin // клавишу ServerBtn и поля HostEdit, PortEdit разблокируем ServerBtn.Enabled:=True; HostEdit.Enabled:=True; PortEdit.Enabled:=True; // закрываем клиента ClientSocket.Active:=False; // очищаем список клиентов UserListView.Items.Clear; // выводим сообщение в ChatMemo ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сессия закрыта.’); // возвращаем тэгу исходное значение ClientBtn.Tag:=0; // возвращаем исходную надпись клавиши ClientBtn.Caption:=’Подключиться’; end; end;


ПроцедурынаOnConnect, OnDisconnect, OnRead клиентаClientSocket. Сначаланачтениесообщенияссервера (OnRead):


procedure TForm1.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); begin // получимтекст, кодкомманды, длинустрокиtext:=Socket.ReceiveText(); com:=StrToInt(Copy(text,1,1)); len:=Length(text)-1; // определениекоммандcase com of // добавимв ChatMemo сообщениессервера0: ChatMemo.Lines.Add(Copy(text,2,len)); // отошлемсвойникнасервер1: ClientSocket.Socket.SendText('1'+NikEdit.Text); // примемстрокуспискапользователей2: begin // очищаемсписокклиентовUserListView.Items.Clear; // добавимключконцастроки (т.к. вырезкасимволовсзадержкой) text:=text+Chr(152); // укажемначальныйсимволpos:=2; // обнулимсчетчиксимволовx:=0; // пробегаемподлинестрокиспискаfor j:=2 to len+1 do begin // записываемвсчетчиксдвигx:=x+1; // еслинайденключ (отделениениковвстроке) if Copy(text,j,1)=Chr(152) then begin // добавимв UserListView строкуUItems:=UserListView.Items.Add; UItems.Caption:=Copy(text,pos,x-1); // укажемсоответствующуюиконкупользователяif pos>2 then UItems.ImageIndex:=0 else UItems.ImageIndex:=1; // изменимтекущуюпозициювстрокеспискаpos:=j+1; // обнулимсчетчиксимволовx:=0; end; end; end; end; end;


Дальше обычное добавление в ChatMemo определенного сообщения:


procedure TForm1.ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket); begin // добавим в ChatMemo сообщение о соединении с сервером ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Подключение к серверу.’); end;


procedure TForm1.ClientSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket); begin // добавим в ChatMemo сообщение о потере связи ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сервер не найден.’); end;


Хранителем информации о пользователях у нас выступает массив, процедура его заполнения и обновления выглядит так:


procedure TForm1.UpdateUserMas; begin // очищаем массив с информацией for i:=1 to 255 do begin UserMas.Status:=0; UserMas.Rec:=False; UserMas.Name:=’Неизвестный’; UserMas.Image:=0; end; // заполняем данные пользователей if ServerSocket.Socket.ActiveConnections<>0 then begin for i:=1 to ServerSocket.Socket.ActiveConnections do begin UserMas.Status:=2; UserMas.Name:=’Неизвестный’; UserMas.Image:=0; // запрашиваем имя (ник) пользователя по его каналу (код команды - 1) ServerSocket.Socket.Connections.SendText(’1′); end; end; end;


Список UserListView обновляется в следующей процедуре:


procedure TForm1.UpdateUserList; begin // очищаем список клиентов UserListView.Items.Clear; // очищаем переменную StrUserList:=''; // обнуляем пометку записи ContList:=0; // пробегаем по диапазону каналов for i:=0 to 255 do begin // если запись не пустая if UserMas.Status<>0 then begin // добавим в UserListView строку UItems:=UserListView.Items.Add; UItems.Caption:=UserMas.Name; UItems.ImageIndex:=UserMas.Image; // если пользователь не записан if UserMas.Rec=False then ContList:=1; // составляем строку пользователей StrUserList:=StrUserList+UserMas.Name+Chr(152); end; end; // если все пользователи отметились, и есть хоть один канал if (ContList=0) and (ServerSocket.Socket.ActiveConnections<>0) then begin // пробегаем по всем открытым каналам for i:=0 to ServerSocket.Socket.ActiveConnections-1 do begin // отправим строку списка пользователей (код команды - 2) ServerSocket.Socket.Connections.SendText(’2′+StrUserList); end; end; end;


Листинг
программы


unit MainUnit;


interface


uses


Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,


Dialogs, StdCtrls, ScktComp, ExtCtrls, ImgList, ComCtrls, jpeg;


type


TForm1 = class(TForm)


ServerSocket: TServerSocket;


ClientSocket: TClientSocket;


PortEdit: TEdit;


NikEdit: TEdit;


TextEdit: TEdit;


ChatMemo: TMemo;


HostEdit: TEdit;


ServerBtn: TButton;


ClientBtn: TButton;


SendBtn: TButton;


Label1: TLabel;


Label2: TLabel;


Label3: TLabel;


Label4: TLabel;


Label5: TLabel;


UserListView: TListView;


Label6: TLabel;


ImageList: TImageList;


ServerTimer: TTimer;


Image1: TImage;


procedure FormCreate(Sender: TObject);


procedure UpdateUserList;


procedure UpdateUserMas;


procedure ServerBtnClick(Sender: TObject);


procedure ClientBtnClick(Sender: TObject);


procedure ServerSocketClientConnect(Sender: TObject;


Socket: TCustomWinSocket);


procedure ServerSocketClientDisconnect(Sender: TObject;


Socket: TCustomWinSocket);


procedure SendBtnClick(Sender: TObject);


procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);


procedure ClientSocketDisconnect(Sender: TObject;


Socket: TCustomWinSocket);


procedure ClientSocketConnect(Sender: TObject;


Socket: TCustomWinSocket);


procedure ServerTimerTimer(Sender: TObject);


procedure TextEditKeyDown(Sender: TObject; var Key: Word;


Shift: TShiftState);


private


{ Private declarations }


public


{ Public declarations }


end;


Type


TUserList = object


Status: Byte;


Rec: Boolean;


Name: String;


Image: Byte;


end;


var


Form1: TForm1;


i, j, com, ContList: Byte;


len, pos, x: Word;


text, StrUserList: String;


UpdDo: Boolean;


Buf: array[0..3] of Byte;


UserMas: array[0..255] of TUserList;


UItems: TListItem;


implementation


{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);


begin


Caption:='Многопользовательскийчат';


Application.Title:=Caption;


PortEdit.Text:='Портсервера';


HostEdit.Text:='Адрессервера';


NikEdit.Text:='Ананим';


TextEdit.Clear;


ChatMemo.Lines.Clear;


end;


procedure TForm1.UpdateUserList;


begin


UserListView.Items.Clear;


StrUserList:='';


ContList:=0;


For i:=0 to 255 do


Begin


If UserMas[i].Status<>0 then


Begin


UItems:=UserListView.Items.Add;


UItems.Caption:=UserMas[i].Name;


UItems.ImageIndex:=UserMas[i].Image;


If UserMas[i].Rec=False then ContList:=1;


StrUserList:=StrUserList+UserMas[i].Name+Chr(152);


end;


end;


If (ContList=0) And (ServerSocket.Socket.ActiveConnections<>0) then


Begin


For i:=0 to ServerSocket.Socket.ActiveConnections-1 do


Begin


ServerSocket.Socket.Connections[i].SendText('2'+StrUserList);


end;


end;


end;


procedure TForm1.UpdateUserMas;


begin


For i:=1 to 255 do


Begin


UserMas[i].Status:=0;


UserMas[i].Rec:=False;


UserMas[i].Name:='Неизвестный';


UserMas[i].Image:=0;


end;


If ServerSocket.Socket.ActiveConnections<>0 then


Begin


For i:=1 to ServerSocket.Socket.ActiveConnections do


Begin


UserMas[i].Status:=2;


UserMas[i].Name:='Неизвестный';


UserMas[i].Image:=0;


ServerSocket.Socket.Connections[i-1].SendText('1');


end;


end;


end;


procedure TForm1.ServerBtnClick(Sender: TObject);


begin


If ServerBtn.Tag=0 then


Begin


ClientBtn.Enabled:=False;


HostEdit.Enabled:=False;


PortEdit.Enabled:=False;


NikEdit.Enabled:=False;


ServerSocket.Port:=StrToInt(PortEdit.Text);


ServerSocket.Active:=True;


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Серверсоздан.');


ServerBtn.Tag:=1;


ServerBtn.Caption:='Закрытьсервер';


ServerTimer.Enabled:=True;


UserMas[0].Status:=1;


UserMas[0].Rec:=True;


UserMas[0].Name:=NikEdit.Text;


UserMas[0].Image:=1;


UpdDo:=True;


end


else


Begin


ServerTimer.Enabled:=False;


UserMas[0].Status:=0;


UserMas[0].Rec:=False;


UserMas[0].Name:='Неизвестный';


UserMas[0].Image:=0;


UpdDo:=True;


UserListView.Items.Clear;


ClientBtn.Enabled:=True;


HostEdit.Enabled:=True;


PortEdit.Enabled:=True;


NikEdit.Enabled:=True;


ServerSocket.Active:=False;


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Серверзакрыт.');


ServerBtn.Tag:=0;


ServerBtn.Caption:='Создатьсервер';


end;


end;


procedure TForm1.ClientBtnClick(Sender: TObject);


begin


If ClientBtn.Tag=0 then


Begin


ServerBtn.Enabled:=False;


HostEdit.Enabled:=False;


PortEdit.Enabled:=False;


ClientSocket.Port:=StrToInt(PortEdit.Text);


ClientSocket.Host:=HostEdit.Text;


ClientSocket.Address:=HostEdit.Text;


ClientSocket.Active:=True;


ClientBtn.Tag:=1;


ClientBtn.Caption:='Отключиться';


end


else


Begin


ServerBtn.Enabled:=True;


HostEdit.Enabled:=True;


PortEdit.Enabled:=True;


ClientSocket.Active:=False;


UserListView.Items.Clear;


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сессиязакрыта.');


ClientBtn.Tag:=0;


ClientBtn.Caption:='Подключиться';


end;


end;


procedure TForm1.ServerSocketClientConnect(Sender: TObject;


Socket: TCustomWinSocket);


begin


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Подключилсяклиент.');


UpdDo:=True;


end;


procedure TForm1.ServerSocketClientDisconnect(Sender: TObject;


Socket: TCustomWinSocket);


begin


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Клиентотключился.');


UpdDo:=True;


end;


procedure TForm1.SendBtnClick(Sender: TObject);


begin


If ServerSocket.Active=True then


For i:=0 to ServerSocket.Socket.ActiveConnections-1 do


ServerSocket.Socket.Connections[i].SendText('0['+TimeToStr(Time)+'] '+NikEdit.Text+': '+TextEdit.Text)


else


ClientSocket.Socket.SendText('0['+TimeToStr(Time)+'] '+NikEdit.Text+': '+TextEdit.Text);


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] '+NikEdit.Text+': '+TextEdit.Text);


TextEdit.Clear;


end;


procedure TForm1.ClientSocketRead(Sender: TObject;


Socket: TCustomWinSocket);


begin


text:=Socket.ReceiveText();


com:=StrToInt(Copy(text,1,1));


len:=Length(text)-1;


Case com of


0: ChatMemo.Lines.Add(Copy(text,2,len));


1: ClientSocket.Socket.SendText('1'+NikEdit.Text);


2: Begin


UserListView.Items.Clear;


text:=text+Chr(152);


pos:=2;


x:=0;


For j:=2 to len+1 do


Begin


x:=x+1;


If Copy(text,j,1)=Chr(152) then


Begin


UItems:=UserListView.Items.Add;


UItems.Caption:=Copy(text,pos,x-1);


If pos>2 then UItems.ImageIndex:=0 else UItems.ImageIndex:=1;


pos:=j+1;


x:=0;


end;


end;


end;


end;


end;


procedure TForm1.ClientSocketConnect(Sender: TObject;


Socket: TCustomWinSocket);


begin


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Подключениексерверу.');


end;


procedure TForm1.ClientSocketDisconnect(Sender: TObject;


Socket: TCustomWinSocket);


begin


ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Серверненайден.');


end;


procedure TForm1.ServerTimerTimer(Sender: TObject);


begin


If ServerSocket.Socket.ActiveConnections<>0 then


Begin


For i:=1 to ServerSocket.Socket.ActiveConnections do


Begin


text:=ServerSocket.Socket.Connections[i-1].ReceiveText();


If text<>'' then


Begin


com:=StrToInt(Copy(text,1,1));


len:=Length(text)-1;


Case com of


0: Begin


ChatMemo.Lines.Add(Copy(text,2,len));


For j:=0 to ServerSocket.Socket.ActiveConnections-1 do


Begin


If (j+1)<>i then ServerSocket.Socket.Connections[j].SendText('0'+Copy(text,2,len));


end;


end;


1: Begin


UserMas[i].Name:=Copy(text,2,len);


UserMas[i].Rec:=True;


UpdateUserList;


end;


end;


end;


end;


end;


If UpdDo=True then


Begin


UpdateUserMas;


UpdateUserList;


UpdDo:=False;


end;


end;


procedure TForm1.TextEditKeyDown(Sender: TObject; var Key: Word;


Shift: TShiftState);


begin


If Key=VK_RETURN then SendBtn.Click;


end;


end.


Заключение


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


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


Приложение


Запущенный сервер:





При подключение к серверу (у сервера):





При подключении к серверу (у клиента):





Отправка сообщений (у сервера и клиента):

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Проектирование и разработка программы ЧАТ для локальной сети

Слов:3439
Символов:36329
Размер:70.96 Кб.