Мегаобучалка Главная | О нас | Обратная связь


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



2019-07-03 190 Обсуждений (0)
Глава II . Создание многопользовательского чата ( Multy - user on - line ) 0.00 из 5.00 0 оценок




 

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., далее нужно указать файл …\bin\dclsockets70.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(); // условие, что пакет не пуст if text<>” then begin {тут обработка строки, выделение составляющих кода команд (com) и пр.} // определение команд case com of код: begin {процедура} end; код: begin {процедура} end; ……………………………………. end; end; end; end; // разрешение на выполнение процедур обновления if UpdDo=True then begin {процедуры} // блокируем разрешение 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 технологий, нет смысла создавать собственную программу чата. Так как в более удобно взять уже готовый, полностью завершенный чат.


Приложение

 

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

 

 

 


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

 

 

 


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

 

 

 


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



2019-07-03 190 Обсуждений (0)
Глава II . Создание многопользовательского чата ( Multy - user on - line ) 0.00 из 5.00 0 оценок









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

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Модели организации как закрытой, открытой, частично открытой системы: Закрытая система имеет жесткие фиксированные границы, ее действия относительно независимы...
Почему человек чувствует себя несчастным?: Для начала определим, что такое несчастье. Несчастьем мы будем считать психологическое состояние...
Как построить свою речь (словесное оформление): При подготовке публичного выступления перед оратором возникает вопрос, как лучше словесно оформить свою...
Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (190)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.013 сек.)