Продолжая тему разработки собственной утилиты администрирования, в данной статье я рассмотрю типовой шаблон программы клиент-сервер, на базе которой можно разрабатывать собственные клиент-серверные приложения. Данный типовой шаблон для простоты понимания и удобства применения будет рассмотрен на примере компонентов 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, чтобы определять момент подключения клиентов. Вставим следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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, в котором будем обрабатывать получаемые сообщения от клиентов:
1 2 3 4 5 6 7 8 9 10 11 12 13 | procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket); var s:string; begin s:=Socket.ReceiveText; log.Lines.Add(s); end; |
Определим метод onClientDisconnect, чтобы фиксировать факт отключения клиента:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 для того, чтобы обрабатывать исключения, возникшие в момент подключения клиента к серверу. Вставим следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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. Вставим следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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. Вставим следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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: К сожалению, такой возможности на данный момент уже нет.
Можно получить ссылочку на собранный проект? Что-то у меня с косяками выходит.
Признаться, шансы не велики. Я передам автору статьи, если будет такая возможность — он с вами свяжется. Сам, к сожалению, помочь не могу — не дельфист.
Увы, судя по всему, у автора нет времени. Но вы можете описать свою проблему здесь, может, кто-нибудь поможет.
Наверно уже поздно, но всё-таки…
В статье только один косяк. Здесь по инструкции у сервера выставляется Active = False.
Таким образом сервер не запускается автоматически при старте программы. Можно или выставить Active = True в свойствах, или прописать в нужном месте, например на нажатие кнопки ss.Active:=True;
А так, полезная статья, спасибо автору!
Подскажите плиз:
В локальной сети все ок, но как соединиться с сервером если у него есть IP адрес (например 45.112.14.391 ) и сетевой адрес ( 192.168.1.5) ?
192.168.1.5 — это локальный ip
чтобы сконектиться с внешним ip 45.112.14.391 — просто укажи его в подключении, но на компе -сервере, ты должен открыть в роутере или брандмауэре порт, по которому будет работать прога (4321) и все получиться
Востановите пожалуйста ссылки. Я сделал всё как написано. в меме клиента пишет «21.12.2013 17:07:41: Невозможно установить соединение с сервером — 192.168.1.3
Сожалею, но такой возможности нет (раньше была).
Тут несколько советов (сразу говорю, я в дельфи — «ни в зуб ногой»), попробуй:
).
1. Указать в параметрах сервера адрес не 127.0.01, а 0.0.0.0 или 192.168.1.3 (похожий совет есть в комментах выше).
2. Воспользоваться советом выше и выставить Active = True (без понятия что это
3. Подключиться к серверу с помощью telnet. Если и telnet не подключается, то хотя бы будет понятно что проблема не в клиенте. Попробуй на этой же машине запустить какой-нибудь заведомо рабочий сервер и подключись на его порт, если тоже не будет работать — проблема в фаерволле.
4. Попробуй подключиться клиентом на любой веб-сервер (80й порт).
Вы забыли указать,что сервак нужно включить.