KVRSOFT - Програмиране на сокети в Delphi
За първи път се запознах с контакти, ако не се лъжа, преди година или половина. Тогава задачата беше да се разработи протокол за приложение, който да изпрати заявка до сървърна машина (работеща на Unix/Linux OS) и да получи отговор чрез сокет канал. Трябва да се отбележи, че за разлика от други протоколи (FTP, POP, SMTP, HTTP и др.), Сокетите са в основата на тези протоколи. По този начин, използвайки гнезда, можете сами да създадете (симулирате) FTP, POP и всеки друг протокол и не непременно вече създаден, но дори и ваш собствен!
Така че нека започнем с теорията. Ако сте отдаден практикуващ (и не виждате алгоритми в очите си), тогава трябва да пропуснете този раздел.
Алгоритъм за работа с сокет протоколи
И така, какво ни позволяват гнездата? Всичко! И това е едно от основните предимства на този метод за обмен на данни в мрежата. Въпросът е, че когато работите с сокет, просто изпращате последователност от символи на друг компютър. Така че с този метод можете да изпращате както прости съобщения, така и цели файлове! Освен това не е необходимо да контролирате коректността на прехвърлянето (както беше при работа с COM портове)!
По-долу е дадена примерна схема за работа с сокети в приложенията на Delphi
Нека анализираме схемата по-подробно:
Изпращането/получаването на данни всъщност е това, за което е била отворена връзката на сокета. Комуникационният протокол също зависи от сървъра;
Затваряне на сокет - след като всички операции са изпълнени, трябва да затворите сокета, използвайки метода Close на компонента TClientSocket (или да зададете свойството Active на False).
Описание на свойствата и методите на компонента TClientSocket
Тук ще се запознаем с основните свойства, методи и събития на компонента TClientSocket.
Активен - показва дали гнездото е отворено или не. Тип: Boolean. Съответно True е отворен, а False е затворен. Това свойство може да се записва;
Хост - низ (Тип: низ), указващ името на хоста на компютъра, към който да се свържете;
Порт - номер на порт (Тип: Цяло число (Word)), към който да се свържете. Валидни стойности са от 1 до 65535;
Услуга - низ (Тип: низ), определящ услугата (ftp, http, поп и т.н.), към която ще бъде свързан портът. Това е вид справка за съответствието на номерата на портове с различни стандартни протоколи;
ClientType - тип връзка. ctNonBlocking - асинхронно предаване на данни, тоест можете да изпращате и получавате данни през сокет, използвайки OnRead и OnWrite. ctBlocking - синхронен (едновременен) трансфер на данни. Събитията OnRead и OnWrite не работят. Този тип връзка е полезен за организиране на обмен на данни с помощта на потоци (т.е. работа с сокет като файл);
Open - отваряне на сокет (подобно на задаването на свойството Active на True);
Close - затваря сокета (подобно на присвояване на False на свойството Active);
OnConnecting - задейства се, когато се установи връзка. Разликата от OnConnect е, че връзката все още не е установена. Обикновено тези междинни събития се използват за актуализиране на състоянието;
OnDisconnect - Повишава се, когато гнездото е затворено. Нещо повече, затваряне както от вашата програма, така и от страната на отдалечен компютър (или поради повреда);
OnError - продължава тъжната тема на предишното събитие:). Възниква, когато възникне грешка в сокет. Трябва да се отбележи, че това събитие няма да ви помогне да уловите грешка в момента на отваряне на сокета (Open). За да избегнете издаването на съобщение за грешка в Windows, трябва да приложите отворените отчети на сокета в блок try.except (обработка на изключения);
OnRead - възниква, когато отдалеченият компютър ви е изпратил някакви данни. Когато се случи това събитие, е възможна обработка на данни;
OnWrite - възниква, когато ви е позволено да записвате данни в сокета.
Практика и примери
Пример 1. Най-проста програма за сокети
При натискане на бутона се извиква манипулаторът на събитието OnClick - Button1Click.
Преди това трябва да въведете името на хоста в първия от TEdits,
а във втория - порта на отдалечения компютър.
НЕ ЗАБРАВЯЙТЕ ДА ПОСТАВАТЕ КОМПОНЕНТА TClientSocket във ФОРМАТА!>
процедура Button1Click (Изпращач: TObject);
ClientSocket1.Port: = StrToInt (Edit2.Text);
процедура ClientSocket1Connect (Изпращач: TObject; Гнездо: TCustomWinSocket);
Ако смятате, че тази примерна програма е напълно безполезна и не може да бъде от полза, дълбоко се заблуждавате. Даденият код е най-простият пример за скенер на портове (PortScanner). Същността на такава помощна програма е да провери дали посоченият порт е активиран и дали е готов да приема/предава данни. Това е принципът зад PortScanner от NetTools Pro.
Следва друг пример, в който текстови съобщения се изпращат и получават през сокет:
Пример 2. Изпращане/получаване на текстови съобщения през гнезда
При щракване върху първия бутон се извиква манипулаторът на събитието OnClick - Button1Click.
Преди това трябва да въведете името на хоста в първия от TEdits,
а вторият е портът на отдалечения компютър. След установяване на връзката
можете да изпращате текстови съобщения, като въвеждате текст в третия TEdit и натискате
вторият бутон TB. За да прекъснете връзката, трябва отново да натиснете първия бутон TB.
Също така трябва да добавим TListBox, в който ще поставим полученото
и изпратени съобщения.
НЕ ЗАБРАВЯЙТЕ ДА ПОСТАВАТЕ КОМПОНЕНТА TClientSocket във ФОРМАТА!>
процедура Button1Click (Изпращач: TObject);
ако ClientSocket1.Активен тогава
ClientSocket1.Port: = StrToInt (Edit2.Text);
процедура ClientSocket1Connect (Изпращач: TObject; Гнездо: TCustomWinSocket);
процедура Button2Click (Изпращач: TObject);
ЗАБЕЛЕЖКА: В някои случаи (в зависимост от сървъра) трябва да изпращате линейна емисия след всяко съобщение:
ClientSocket1.Socket.SendText (Edit3.Text # 10);
Работа с поток от сокет
„Как иначе можете да работите със сокет?“, Питате вие. Естествено, горният метод не е най-доброто решение. Има много методи за организиране на работа с гнезда. Ще дам само още едно допълнително - работа през потока. Със сигурност много от вас вече имат опит с, ако не с потоци, то с файлове - със сигурност. За тези, които не знаят, потокът е канал за обмен на данни, работата с който е подобна на работата с обикновен файл. Примерът по-долу показва как да настроите поток за работа с сокет:
Пример 3. Поток за работа със сокет
процедура ClientSocket1Connect (Изпращач: TObject; Гнездо: TCustomWinSocket);
свържете го с сокета (60000 - изчакване в ms)>
MySocket: = TWinSocketStream.Create (Socket, 60000);
(в този пример - 100) и връща True, ако има поне едно
байт за данни, False, ако няма данни от потока.>
докато не MySocket.WaitForData (100)
прозоречни елементи и дава време на други програми. Ако този оператор
не беше и данните нямаше да бъдат получени дълго време,
системата би замръзнала леко
MySocket.Read (c, 1);
(в този пример - 1) към посочената променлива от определен тип
(в примера в променлива c от тип Char). Моля, имайте предвид, че,
че Read, за разлика от ReadBuffer, не задава стриктно
ограничения върху количеството получена информация. Тези. Прочетете четете
не повече от n байта от потока (където n е определен номер).
Тази функция връща броя на получените байтове с данни.>
MySocket.Write (c, 1);
че Write пише данни в потока.>
ЗАБЕЛЕЖКА: За да използвате поток, не забравяйте да зададете свойството ClientType на ctBlocking.
Изпращане и получаване на сложни данни
Понякога е необходимо да се изпращат по мрежата не само прости текстови съобщения, но и сложни структури (типът запис в Pascal) или дори файлове. И тогава трябва да използвате специални оператори. Някои от тях са изброени по-долу:
Методи на TClientSocket.Socket (TCustomWinSocket, TClientWinSocket):
SendBuf (var Buf; Count: Integer) - Изпращане на буфер през сокет. Буферът може да бъде от всякакъв тип, било то запис или обикновено цяло число. Буферът се определя от параметъра Buf, като с втория параметър трябва да посочите размера на прехвърлените данни в байтове (Count);
SendText (const S: string) - Изпраща текстов низ през сокет. Този метод беше обсъден в пример 2 (виж по-горе);
SendStream (AStream: TStream) - Изпратете съдържанието на посочения поток през сокет. Препратеният поток трябва да е отворен. Потокът може да бъде от всякакъв тип - файл, от RAM и др. Описанието за директна работа с потоци е извън обхвата на тази статия;
Всички изброени методи съответстват на методите Receive ... Описанието им може да бъде намерено във файла за помощ на Delphi (помощ за VCL).
Упълномощаване на сървъра
Пример 4. Упълномощаване
TEdit - Edit3 и Edit4, за да въведете потребителско име и парола>
процедура ClientSocket1Connect (Изпращач: TObject; Гнездо: TCustomWinSocket);
вход, парола: низ;
MySocket: = TWinSocketStream.Create (Socket, 60000);
за да може сървърът да отдели данните за вход и парола.>
вход: = Редактиране 3. Текст # 10;
парола: = Edit4.Text # 10;
MySocket.Write (вход, дължина (Edit3.Text) 1);
MySocket.Write (парола, дължина (Edit4.Text) 1);
докато не MySocket.WaitForData (100)
MySocket.Read (c, 1);
(това е само пример). След това изпълняваме необходимите действия
(получаване/изпращане на данни) и затваряне на потока.>
В тази статия съм написал само малко от това, което може да се каже за гнездата. Може би когато имам нов прилив на енергия, ще допълня тази статия с още по-интересен материал.
В близко бъдеще планирам и статия за сокет сървъри (TServerSocket).
- Програмиране, уроци и примери за сравнение на низове в CMPS
- Вместо поле - пустиня - портал за цветя Vash Sad!
- Вместо предговор
- 1 Анализ на броя на служителите
- Анатомия на протест - 2