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

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», возникающее при попытке осуществления подключения к серверу, который недоступен.

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

Update: Тут были некоторые ссылки на скачивание, но они стали битыми. По просьбе можно попробовать восстановить.
Update 2: К сожалению, такой возможности на данный момент уже нет.

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.2/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.3/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.4/5.5/5. (23 голосов, средний: 4,65 из 5)
Загрузка...
  1. Николай
    26 мая 2013 в 13:19 | #1

    Можно получить ссылочку на собранный проект? Что-то у меня с косяками выходит.

  2. lizz
    26 мая 2013 в 23:50 | #2

    @Николай
    Признаться, шансы не велики. Я передам автору статьи, если будет такая возможность - он с вами свяжется. Сам, к сожалению, помочь не могу - не дельфист.

  3. lizz
    1 июня 2013 в 15:41 | #3

    @Николай
    Увы, судя по всему, у автора нет времени. Но вы можете описать свою проблему здесь, может, кто-нибудь поможет. :)

  4. Hz
    17 июня 2013 в 09:52 | #4

    Наверно уже поздно, но всё-таки...
    В статье только один косяк. Здесь по инструкции у сервера выставляется Active = False.
    Таким образом сервер не запускается автоматически при старте программы. Можно или выставить Active = True в свойствах, или прописать в нужном месте, например на нажатие кнопки ss.Active:=True;
    А так, полезная статья, спасибо автору! :)

  5. buddy
    2 сентября 2013 в 15:49 | #5

    Подскажите плиз:
    В локальной сети все ок, но как соединиться с сервером если у него есть IP адрес (например 45.112.14.391 ) и сетевой адрес ( 192.168.1.5) ?

  6. Алексей
    14 октября 2013 в 10:06 | #6

    192.168.1.5 - это локальный ip

    чтобы сконектиться с внешним ip 45.112.14.391 - просто укажи его в подключении, но на компе -сервере, ты должен открыть в роутере или брандмауэре порт, по которому будет работать прога (4321) и все получиться

  7. Аноним
    21 декабря 2013 в 18:08 | #7

    Востановите пожалуйста ссылки. Я сделал всё как написано. в меме клиента пишет "21.12.2013 17:07:41: Невозможно установить соединение с сервером - 192.168.1.3
    "

  8. lizz
    23 декабря 2013 в 11:55 | #8

    @Аноним
    Сожалею, но такой возможности нет (раньше была).

    Тут несколько советов (сразу говорю, я в дельфи - "ни в зуб ногой"), попробуй:
    1. Указать в параметрах сервера адрес не 127.0.01, а 0.0.0.0 или 192.168.1.3 (похожий совет есть в комментах выше).
    2. Воспользоваться советом выше и выставить Active = True (без понятия что это :) ).
    3. Подключиться к серверу с помощью telnet. Если и telnet не подключается, то хотя бы будет понятно что проблема не в клиенте. Попробуй на этой же машине запустить какой-нибудь заведомо рабочий сервер и подключись на его порт, если тоже не будет работать - проблема в фаерволле.
    4. Попробуй подключиться клиентом на любой веб-сервер (80й порт).

  9. Diman
    5 апреля 2014 в 21:02 | #9

    Вы забыли указать,что сервак нужно включить.

  10. Elena
    28 апреля 2016 в 18:38 | #10

    У меня вопрос,как-нибудь возможно проверить работу на одном компьютере? Клиент работает вроде,пишет "Установить соединение с клиентом 127.0.0.1",это верно или же нет

  11. diomed
    4 августа 2016 в 07:42 | #11

    Метод OnConnect неправильно обрабатывается. У меня пишет что коннект установлен, хотя это невозможно. Хотя на совсем уже неверные адреса не пишет.

  12. Евгений
    4 августа 2016 в 19:01 | #12

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

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