Рейтинг@Mail.ru

Delphi: Пишем шаблон клиент-серверного приложения.


Продолжая тему разработки собственной утилиты администрирования, в данной статье я рассмотрю типовой шаблон программы клиент-сервер, на базе которой можно разрабатывать собственные клиент-серверные приложения. Данный типовой шаблон для простоты понимания и удобства применения будет рассмотрен на примере компонентов ClientSocket и ServerSocket.

Примечание

Для тех, кто не в курсе, что значит клиент-серверное приложение, поясню: это комплекс программ (модулей) состоящий из двух частей – клиентской и серверной. Серверная часть является «главной»- так называемый командный пункт, на который возложена задача поддержания связи со всеми клиентами и раздача команд управления, соответствующих их функционалу (управление клиентами). Клиентская же часть является второстепенной, но не менее важной, так как является важным и связующим элементом, позволяющим выполнять удаленные команды (функции) на компьютере, на котором установлен.
Компоненты ClientSocket и ServerSocket, которые мы будем использовать, находятся на вкладке Internet. Если на этой вкладке у Вас нет этих компонентов (а по умолчанию при установке Delphi7 они не ставятся), необходимо установить их самостоятельно (пакет dclsocketsXX.bpl). Данный пакет можно найти на установочном диске Delphi7 (или в папке C:\Temp, куда распаковывается дистрибутив перед установкой – C:\Temp\delphi7\install\program files\borland\delphi7\bin\) или можете его скачать отсюда. Чтобы установить данный пакет, запустите Delphi7. Зайдите в меню Component->Install Packages. В появившемся окне нажмите кнопку «Add» и укажите место, где расположен пакет dclsocketsXX.bpl. После этого жмите ОК. Компонент на месте. ;)

Надеюсь все объяснил доступно =). А теперь приступим к делу и начнем мы с серверной части. Для этого создадим проект и скинем на форму компонент ServerSocket. В настройках компонента ServerSocket укажем следующее:

Active = false
Name = ss
Port = 4321
ServerType = stNonBlocking

А также для удобства скинем компонент Memo, в который будем выводить всякую инфу. Дадим имя компоненту log.

Далее, для компонента ServerSocket определяем метод onClientConnect, чтобы определять момент подключения клиентов. Вставим следующий код:

procedure TForm1.ssClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.Lines.Add(formattedDateTime+': Есть коннект c '+Socket.RemoteAddress);
  { далее вы можете вставить свой код }
end;

А теперь определим метод onClientRead, в котором будем обрабатывать получаемые сообщения от клиентов:

procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  s:string;
begin
  s:=Socket.ReceiveText;
  log.Lines.Add(s);
end;

Определим метод onClientDisconnect, чтобы фиксировать факт отключения клиента:

procedure TForm1.ssClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.Lines.Add(formattedDateTime+': Клиент '+socket.RemoteAddress+' отключился.');
end;

На этом с серверной частью покончено =).

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

Active = false
Name = сs
Port = 4321
ClientType = ctNonBlocking
Address = 127.0.0.1

Для простоты пояснения я в Address указал «петлю». Но для гибкости приложения рекомендую это поле обрабатывать программно, во время CreateForm при обработке конфигурационного файла, в котором можно указывать нужный IP-адрес сервера.

Здесь также для удобства скинем на форму компонент Memo, в который будем выводить техническую инфу. Имя дадим соответствующее log.

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

procedure TForm1.csError(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
 if ErrorEvent= eeConnect  then
  begin
    cs.Active:=false;
      {добавить запись в журнал};
    mydate:=Now;
    DateTimeToString(formattedDateTime, 'c', myDate);
    log.lines.Add(formattedDateTime+': Невозможно установить соединение с сервером - '+cs.Address);
  end;
  ErrorCode:=0;
  { далее вы можете вставить свой код }
end;

Теперь определим метод onConnect. Вставим следующий код:

procedure TForm1.csConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.lines.Add(formattedDateTime+': Соединение с сервером - '+socket.RemoteAddress+' установлено.');
end;

И чтобы фиксировать момент потери связи с сервером, определим метод onDisconnect:

procedure TForm1.csDisconnect(Sender: TObject; Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now; //получим текущее время
  DateTimeToString(formattedDateTime, 'c', myDate); //преобразуем в строку
  log.Lines.Add(formattedDateTime+': Соединение с сервером '+socket.RemoteAddress+' потеряно.');
end;

Таймер настроим так:

Enabled = true
Name = te
Interval = 5000

И определяем метод onTimer. Вставим следующий код:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if not cs.Active then
  begin
    cs.Active:=true;
  end;
  cs.Socket.SendText('ping client');
end;

Данный код проверяет наличие соединения с сервером и в случае его отсутствия пытается его установить.
И каждые 5 секунд отправляет серверу сообщение «ping client».

Вот примерно так выглядит типовой шаблон приложения «клиент-сервер».

Примечание

Хотел бы обратить внимание на обработчик onError тех, кто ранее не знал как избавиться от злосчастного сообщения – «Asynchronous socket error 10061″, возникающее при попытке осуществления подключения к серверу, который недоступен.

Рабочий пример можно скачать отсюда.

Если есть кому что добавить или задать вопрос по теме – прошу отписываться в комментах ;)

C0ffe1n Программирование, прикладное, сетевое , , , ,

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1 звезда2 звезды3 звезды4 звезды5 звёзд (2 голосов, средний: 3.00 из 5)
Loading ... Loading ...

  1. Сергей
    21 Апрель 2010 в 11:33 | #1

    Пример про то, как избавиться от ошибки «Asynchronous socket error 10061″ не рабочий… обновите ссылку, пожалуйста…

    • 21 Апрель 2010 в 21:08 | #2

      пример рабочий, ток в исходнике каким то нелепым образом обработчик ошибки закоментирован, просто раскоментируйте и заново скомпилируйте пример и все будет окей ;)

  2. Andrew
    23 Июль 2010 в 12:09 | #3

    Есть необходимость небольшую базу данных, созданную в Access, переписать на Delphi с использованием «клиент-сервер».
    Может, чем-нибудь подсобишь?

  3. 25 Июль 2010 в 17:00 | #4

    @Andrew
    Coffein пока вне зоны досягаемости, будет после 27го. Тыкну чтобы отписался как будет возможность, но на сколько известно мне, с Access он не работал.

    P.S. Сам delphi не знаю, ничем помочь не могу :).

  4. 28 Июль 2010 в 11:21 | #5

    @Andrew
    Это зависит от техзадания, вообщем пиши в аську, обсудим, может чем и подсоблю

  1. Пока что нет уведомлений.