- •Система обмена сообщениями
- •Содержание
- •Введение
- •1.Теоретический анализ и проектирование
- •1.1. Постановка задачи. Функции системы.
- •1.2. Архитектура системы.
- •1.3 Протокол. Описание протокола взаимодействия
- •Команды клиента
- •1.4 Взаимодействие клиента и сервера
- •1.Подключение клиента:
- •2.Отключение клиента:
- •3.Отправка общего сообщения:
- •4.Отправка приватного сообщения:
- •5.Отправка Файла:
- •2. Программная реализация
- •2.1 Используемые компоненты.
- •2.2 Описание свойств и методов
- •2.3 Исходный код Сервера отвечающий за сетевое взаимодействие
- •2.4 Исходный код Клиента отвечающий за сетевое взаимодействие
- •2.5 Порядок работы с программой
- •2.5.1 Работа с сервером.
- •2.5.2 Работа с клиентом.
- •2.6 Тестирование системы
- •Заключение
- •Используемые источники
2.3 Исходный код Сервера отвечающий за сетевое взаимодействие
//К серверу подключился клиент (OnClientConnect)
var i: Integer;
begin
{Кто-то присоединился или отсоединился? Запрашиваем у всех
юзеров их имена}
ListBox1.Items.Clear;
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText('#N');
memo1.Lines.Add(timetostr(now)+': '+'Пользователь подключился. В сети:'+inttostr(ServerSocket1.Socket.ActiveConnections))
end;
//От сервера отключился клиент (OnClientDisconnect)
var i: Integer;
begin
{Кто-то присоединился или отсоединился? Нет проблем! Запрашиваем у всех
юзеров их имена}
ListBox1.Items.Clear;
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText('#N');
memo1.Lines.Add(timetostr(now)+': '+'Пользователь отключился. В сети:'+inttostr(ServerSocket1.Socket.ActiveConnections))
end;
//Сервер получает данные от клиента (OnClientRead)
var s,s1: string;
i: Integer;
iLen: Integer;
Bfr: Pointer;
Name:string;
filename:string;
begin
{сохраняем в s присланную нам строку}
s := Socket.ReceiveText;
{Если кто-то шлёт файл}
if Copy(s,1,2) = '#F' then
begin
Delete(s,1,2);
filename:=s;
{Процедура создания файла}
STR_create(filename);
exit;
end;
{Кто-то хочет переслать всем файл}
if Copy(s,1,2) = '#S' then
begin
Delete(s,1,2);
FStream.Destroy;
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
begin
serverSocket1.Socket.Connections[i].SendText('#F'+s);
serverSocket2.Socket.Connections[i].SendStream(TFileStream.Create('temp/'+s, fmOpenReadWrite or fmShareDenyWrite));
end;
exit;
end;
{кто-то шлёт своё имя}
if Copy(s,1,2) = '#N' then
begin
Delete(s,1,2);
{Добавляем его в юзер лист}
ListBox1.Items.Add(s);
{Записываем в s команду для посылки нового списка юзеров}
s := '#U';
for i := 0 to ListBox1.Items.Count-1 do
s := s+ListBox1.Items[i]+';';
{...и рассылаем этот список всем клиентам}
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText(s);
Exit;
end;
{Если кто-то кинул сообщение - рассылаем его всем клиентам}
if (Copy(s,1,2) = '#M')or(Copy(s,1,2) = '#P') then begin
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText(s);
Exit;
end;
end;
//Получение файла (Файловый сервер)
var s,s1: string;
i: Integer;
iLen: Integer;
Bfr: Pointer;
begin
iLen := Socket.ReceiveLength;
GetMem(Bfr, iLen);
try
Socket.ReceiveBuf(Bfr^, iLen);
FStream.Write(Bfr^, iLen);
finally
FreeMem(Bfr);
end;
end;
end.
2.4 Исходный код Клиента отвечающий за сетевое взаимодействие
//Кнопка подключения к серверу
var
host,port:string;
begin
{Проверка введены ли данные(ip,port,nickname)}
if (edit2.Text='') or (edit3.Text='') or (edit4.Text='') then
statusbar2.Panels[0].Text:='Заполните все поля'
else
begin
{Если уже есть подключение}
if ClientSocket1.Active then
begin
host:=edit2.Text;
port:=edit3.Text;
Nickname:=edit4.Text;
ClientSocket1.Host:=host;
ClientSocket1.port:=strtoint(port);
ClientSocket1.Open;
ClientSocket2.Host:=ClientSocket1.host;
ClientSocket2.port:=ClientSocket1.port+50;
ClientSocket2.Open;
end
{Если нет подключение}
else
ClientSocket1.Close;
ClientSocket2.Close;
host:=edit2.Text;
port:=edit3.Text;
Nickname:=edit4.Text;
ClientSocket1.Host := host;
ClientSocket1.Port := StrToInt(port);
Nickname:=edit4.Text;
ClientSocket1.Open;
ClientSocket2.Host:=ClientSocket1.host;
ClientSocket2.port:=ClientSocket1.port+50;
ClientSocket2.Open;
end;
end;
//Кнопка отключения от сервера
Begin
{Закрытие подключения}
ClientSocket1.Close;
ClientSocket2.Close;
end;
//Команды от сервера
var s,from_,to_: string;
temp:integer;
begin
{присваиваем s полученную от сервера строку}
s := Socket.ReceiveText;
if Copy(s,1,2) = '#F' then
begin
Delete(s,1,2);
FStream := TFileStream.Create('temp\'+s, fmCreate or fmShareDenyWrite);
exit;
end;
{Если сервер посылает нам Новый Ник}
if Copy(s,1,2) = '#K' then begin
Delete(s,1,2);
if copy(s,1,pos(';',s)-1)=NickName then begin
Delete(s,1,pos(';',s));
ShowMessage('Администратор изменил ваше имя на: -'+S);
edit4.Text:=S;
button3.Click;
button2.Click;
exit;
end;
exit;
end;
{Если сервер посылает нам User List}
if Copy(s,1,2) = '#U' then begin
Delete(s,1,2);
Temp:=0;
{Чистим ListBox1}
ListBox1.Items.Clear;
{Добавляем по одному юзеру в список. Имена юзеров разделены знаком ";"}
while Pos(';',s) > 0 do begin
ListBox1.Items.Add(Copy(s,1,Pos(';',s)-1));
Delete(s,1,Pos(';',s));
end;
exit;
END;
{Если нам прислали общее сообщение (видимое для всех юзеров)}
if Copy(s,1,2) = '#M' then begin
Delete(s,1,2);
{Добавляем его в Memo1}
richedit1.Lines.Insert(0,Copy(s,1,Pos(';',s)-1)+'> '+ Copy(s,Pos(';',s)+1,Length(s)-Pos(';',s)));
Exit;
end;
{Если нам прислали запрос на наше имя юзера}
if Copy(s,1,2) = '#N' then begin
{Посылаем ответ}
Socket.SendText('#N'+nickname);
Exit;
end;
{Если нам прислали приватное сообщение (или не нам :) )}
if Copy(s,1,2) = '#P' then begin
Delete(s,1,2);
{Выделяем в to_ - кому оно предназначено}
to_ := Copy(s,1,Pos(';',s)-1);
Delete(s,1,Pos(';',s));
{Выделяем в from_ - кем отправлено}
from_ := Copy(s,1,Pos(';',s)-1);
Delete(s,1,Pos(';',s));
{Если оно для нас, или написано нами - добавляем в Memo1
(иногда полезно убрать этот оператор if :) )}
if (to_ = nickname)or(from_ = nickname) then
begin
richedit1.Lines.Insert(0,from_+' (private) > '+s);
RichEdit1.SelStart:=0;
RichEdit1.SelLength:=RichEdit1.Lines[1].Length;
RichEdit1.selAttributes.Color:= clred;
Exit;
end;
end;
if Copy(s,1,2) = '#D' then begin
Delete(s,1,2);
if s=nickname then begin
button3.Click;
ShowMessage('Вы отключены Администратором');
exit;
end;
end;
if Copy(s,1,2) = '#A' then begin
Delete(s,1,2);
if copy(s,1,pos(';',s)-1)=NickName then begin
Delete(s,1,pos(';',s));
ShowMessage('Администратор: -'+S);
exit;
end;
exit;
end;
end;
//Получение файла
var s,s1: string;
i: Integer;
iLen: Integer;
Bfr: Pointer;
begin
iLen := Socket.ReceiveLength;
GetMem(Bfr, iLen);
try
Socket.ReceiveBuf(Bfr^, iLen);
FStream.Write(Bfr^, iLen);
finally
FreeMem(Bfr);
end;
end;
//Отправка сообщения
var s: string;
begin
if (CheckBox1.Checked)and(ListBox1.ItemIndex < 0) then begin
ShowMessage('Чтобы послать приватное сообшение, сначала выберите получателя!');
Exit;
end;
{Если это приватное сообщение}
if CheckBox1.Checked=true then
s := '#P'+ListBox1.Items[ListBox1.ItemIndex]+';' {добавляем спец.команду и адресат}
else {А если не очень приватное?}
s := '#M'; {Просто спец.команду}
{Добавляем наше имя (от кого) и само сообщение}
s := s+nickname+';'+Edit1.Text;
{Посылаем все это добро по сокету}
ClientSocket1.Socket.SendText(s);
{И снова ждем ввода в уже чистом TEdit-е}
Edit1.Text := '';
ActiveControl := Edit1;
end;
//Отправка файла
begin
FStream.Free;
opendialog1.Execute;
ClientSocket1.Socket.SendText('#F'+ExtractFileName(opendialog1.FileName));
ClientSocket2.Socket.SendStream(TFileStream.Create(opendialog1.FileName, fmOpenReadWrite or fmShareDenyWrite));
ClientSocket1.Socket.SendText('#S'+ExtractFileName(opendialog1.FileName));
FStream.Free;
