Delphi rozetkasına qoşulma yoxlanışı. Delfi. Delphi-də soket proqramlaşdırması. Mürəkkəb məlumatların göndərilməsi və qəbulu

Sockets (socket (ingilis dilində) - birləşdirici, yuva) proseslər arasında məlumat mübadiləsini təmin edən proqram interfeysidir.

Şəbəkədə rozetka rabitəsinin əsas üstünlüklərindən biri onun çevikliyidir. Soketlərlə işləməyin əsas prinsipi baytların ardıcıllığını başqa bir kompüterə göndərməkdir, bu, sadə mətn mesajı və ya fayl ola bilər.

İki növ rozetkanı ayırd etmək vacibdir: müştəri rozetkaları , və server yuvaları .

Delphi-də "müştəri" tipli rozetkalarla işləmək üçün bir komponent var TClientSocket, komponentdən istifadə edərək "server" yuvaları ilə işləyə bilərsiniz TServerSocket.

Komponentlərin quraşdırılması

Çox vaxt TServerSocket və TClientSocket komponentləri standart Delphi quraşdırma paketinə daxil edilmir, lakin onlar ayrıca quraşdırıla bilər.

"İnternet" komponentləri sekmesine keçin və orada TServerSocket və TClientSocket komponentlərinin olub olmadığını yoxlayın, əgər yoxdursa, onları quraşdırın. "Komponent/Paketləri quraşdırın" menyusuna gedin, sonra "Əlavə et" düyməsini basın. Açılan dialoq qutusunda siz “dclsocketsXX.bpl” faylını tapmalısınız (o, Delphi ilə qovluqda yerləşən bin qovluğunda yerləşir), burada XX sizin Delphi-nin ədədi versiya nömrəsidir. Faylı tapın, Aç klikləyin və Paketləri Quraşdırma pəncərəsində OK düyməsini basın. İndi "İnternet" sekmesinde iki komponent peyda oldu - TServerSocket və TClientSocket.

Müştəri soketləri ilə işləmək (tClientSocket)

1) Port və Host xüsusiyyətlərinin tərifi. Uğurlu əlaqə xüsusiyyətləri üçün limanEv sahibi TClientSocket komponentinə bəzi dəyərlər təyin edilməlidir. Port xüsusiyyətində qoşulma üçün port nömrəsini göstərməlisiniz (1 - 65535, lakin 1001 - 65535 diapazonundan götürmək daha yaxşıdır, çünki 1000-ə qədər rəqəmlər sistem xidmətləri tərəfindən tutula bilər).

Ev sahibi- qoşulmaq istədiyiniz kompüterin host adı və ya IP ünvanı. Məsələn, rus.delphi.com və ya 192.128.0.0.

2) rozetkanın açılması. Soketi bir kompüterdən digərinə ötürülən simvolların növbəsi kimi nəzərdən keçirəcəyik. Metodu çağıraraq rozetka aça bilərsiniz açıq(TClientSocket komponenti) və ya dəyər təyin etməklə Doğruəmlak Aktiv. Burada uğursuz bir əlaqə halında bir istisna işləyicisi qoymaq faydalı olardı.

3) Məlumatların göndərilməsi/qəbul edilməsi.

4) Rozetkanın bağlanması. Məlumat mübadiləsi başa çatdıqdan sonra metodu çağıraraq yuvanı bağlamalısınız yaxın komponent TClientSocket və ya dəyər təyin etməklə Yalanəmlak Aktiv.

TClientSocket komponentinin əsas xassələri

Soketin açıq və ya qapalı olub-olmadığını göstərən göstərici. Açıldı - Həqiqi dəyər, bağlandı - Yanlış dəyər. Yazmaq üçün əlçatandır.

Qoşulmaq üçün host adı

Qoşulmaq üçün kompüterin IP ünvanı. Host-dan fərqli olaraq burada yalnız IP göstərilə bilər. Fərq ondadır ki, əgər Host-da hərfi kompüter adı varsa, IP DNS-dən tələb olunacaq

Qoşulacaq kompüterin port nömrəsi (1-65535)

Müştəri Tipi

Məlumat ötürmə növünü ehtiva edir:

ctBloklama- sinxron ötürmə ( OnOxuOnWrite işləmir). Sinxron əlaqə növü axın məlumat mübadiləsi üçün uyğundur;

ctNonBlocking- asinxron ötürmə (məlumatların göndərilməsi/qəbul edilməsi hadisələrdən istifadə etməklə həyata keçirilə bilər OnOxuOnWrite)

TClientSocket Komponentinin Əsas Metodları

Soketi açır (Aktiv xüsusiyyəti True olaraq təyin edir)

Soketi bağlayır (Aktiv xüsusiyyəti Yanlış olaraq təyin edir)

TClientSocket komponentinin əsas hadisələri

OnConnect

Bağlantı qurulduqda baş verir. İşləyicidə artıq avtorizasiyaya və ya məlumat göndərməyə/qəbul etməyə başlaya bilərsiniz

OnConnecting

Bağlandıqda da baş verir. OnConnect-dən onunla fərqlənir ki, əlaqə hələ qurulmayıb. Ən çox, məsələn, statusu yeniləmək üçün istifadə olunur

OnDisconnect

Hadisə, rozetka proqramınız, uzaq kompüter tərəfindən və ya nasazlıq səbəbindən bağlandıqda baş verir

Hadisə bir səhv üzərində qaldırılır. Soket açılarkən, bu hadisə xətanı tutmağa kömək etməyəcək. Windows-dan səhv mesajının qarşısını almaq üçün "açıq ifadələri" daxil etməklə daxili istisnaların idarə edilməsinə diqqət yetirmək daha yaxşıdır. cəhd edin..istisna »

OnLookup

Hadisə DNS-dən IP ünvanı almağa çalışarkən baş verir

Hadisə uzaq kompüter sizə bəzi məlumatları göndərdikdə baş verir. OnRead-a zəng edərkən qəbul edilən məlumatları emal etmək mümkündür

Proqramınızın rozetkaya məlumat yazmasına icazə verildikdə hadisə baş verir

Bu məqalə əsas xassələri və funksiyaları əhatə edəcəkdir Delphi komponentləri: TClientSocket və TServerSocket - TCP\IP protokolundan istifadə edərək şəbəkə ilə işləmək üçün istifadə olunur.

Diqqət!Əgər siz Delphi-nin 6.0-dan yuxarı versiyasından istifadə edirsinizsə, o zaman əvvəlcə Sockets Components-i quraşdırmalısınız, Delphi-nin bütün versiyalarında bu aşağıdakı kimi aparılır:

  • Paketləri Quraşdır... dialoq qutusuna keçin: (Əsas menyu) Komponent -> Paketləri Quraşdırın;
  • Əlavə et... düyməsinə klikləyin, bundan sonra biz Delphi-nin Bin qovluğunu tapırıq (məsələn: C:\Program Files\Borland\Delphi 7\bin və ya C:\Program Files\Embarcadero\RAD Studio\7.0\Bin);
  • Tapılmış Bin qovluğunda biz artıq fayl axtarırıq dclsockets [burada nömrələr].bpl, OK düyməsini basın;
  • Biz xoşbəxtik, çünki indi İnternet nişanının komponentlər paneli sekmesinde iki gözəl komponentimiz TServerSocket və TClientSocket var.

Hər hansı bir şəbəkə proqramlarını inkişaf etdirərkən, inkişaf adətən həmişə serverdən başlayır (əlbəttə ki, komandanız varsa, front-end dizaynerləri müştəri üzərində işləməyə başlaya bilər). Serveri həyata keçirmək üçün təəccüblüdür ki, TServerSocket-dən istifadə etməlisiniz.

Əsas xüsusiyyətlər:

  • Aktiv– məntiqi tipli sahə, doğru təyin edildikdə – server işə salınır, həm xüsusi dəyərlər təyin etməklə, həm də ServerSocket1.Open (… Active:=true;) və ya ServerSocket1.Close (… Active:=false) çağırmaqla istifadə edilə bilər. funksiyaları.
  • liman- serverin qulaq asacağı (müştəriləri qəbul edəcəyi) port, diapazon daxilində sistemdəki digər serverlər tərəfindən tutulmayan istənilən dəyər tam.

Əsas hadisələr:

  • OnListen- server dinləmə rejiminə qurulduqda çağırılır, serverin faktiki başlama vaxtını təyin etmək lazım olduqda istifadə edilə bilər.
  • OnClientRead– müştəridən məlumat alındığı anda çağırılır.
  • OnClient Error
  • OnClientConnect- Yeni müştəri serverə qoşulduqda çağırılır.
  • OnClientDisconnect- hadisənin əksi, OnClientConnect

hər bir hadisə funksiyasının atributu var Soket: TCustomWinSocket, içində olduğumuz yuva obyektinə göstərici Bu an iş, əgər hadisəyə səbəb olan müştəri ilə bir şeyə cavab vermək və ya bir şey etmək lazımdırsa, bu xüsusi obyektdən istifadə etməliyik, bütün digər hallarda istifadə edirik ServerSocket1.Socket, vəziyyət müştəri komponenti ilə oxşardır.

Yalnız oxunan xüsusiyyətlər və funksiyalar:

  • – aktiv qoşulmaların sayını qaytarır.
  • ServerSocket1.Socket.Connections– TCustomWinSocket tipli obyektlər massivi, müştərilərlə əlaqəli bütün obyektlərin massivi, indeks sayı 0-dan başlayır, massivin uzunluğu bərabərdir ServerSocket1.Socket.ActiveConnections.
  • ServerSocket1.Socket.Connections massivinin elementlərinə və server hadisə funksiyasına ötürülən Socket atributuna tətbiq olunan funksiyalar və xüsusiyyətlər:
  • Socket.LocalHost
  • Socket.LocalAddress– serverin IP-ni qaytarır.
  • Socket.RemoteHost
  • Socket.RemoteAddress– müştərinin IP-ni qaytarır.
  • Socket.ReceiveText- müştəridən alınan mətn mesajını qaytarır, bundan sonra buferi təmizləyir, yalnız 1 dəfə, 1 qəbul üçün istifadə edilə bilər.
  • Socket.SendText(Mətn)– müştəriyə Text tipli mətn mesajı göndərir simli.

TClientSocket komponenti üçün hər şey demək olar ki, eynidir, yalnız əksinə + server və müştəri arasında əsas vizual fərq, sistemdəki server 1 port dəyəri ilə işə salına bilər, yalnız RAM sizi sayında məhdudlaşdırır. müştərilər.

Əsas xüsusiyyətlər:

  • Aktiv– məntiqi tipli sahə, doğru olaraq təyin edildikdə – müştəri serverə qoşulmağa çalışır, həm xüsusi dəyərlər təyin etməklə, həm də ClientSocket1.Open (… Active:=true;) və ya ClientSocket1.Close (… Active) çağırmaqla istifadə edilə bilər. :=false) funksiyaları .
  • liman– müştərinin serverə qoşula biləcəyi port, diapazon daxilində istənilən dəyər tam.
  • ünvanı– Server növünün IPv4 ünvanı simli müştərinin qoşulacağı nümunə 255.255.255.255.

Əsas hadisələr:

  • OnOxu– şimaldan məlumat alındıqda çağırılır.
  • OnError- Məlumat ötürülməsində xəta baş verdikdə çağırılır.
  • OnConnecting- Müştəri serverə qoşulduqda çağırılır.
  • OnDisconnect- hadisənin əksi, OnConnecting, müştərinin serverdən ayrılması zamanı çağırılır.

Yalnız oxunan xüsusiyyətlər və funksiyalar:

  • ClientSocket1.Socket.SendText() simli
  • Socket.LocalHost– şəbəkədəki müştərinin adını qaytarır.
  • Socket.LocalAddress– müştərinin IP-ni qaytarır.
  • Socket.RemoteHost– şəbəkədəki serverin adını qaytarır.
  • Socket.RemoteAddress– serverin IP-ni qaytarır.
  • Socket.ReceiveText– serverdən alınan mətn mesajını qaytarır, bundan sonra o, buferi təmizləyir, yalnız 1 dəfə, 1 qəbul üçün istifadə edilə bilər.
  • Socket.SendText(Mətn)– serverə Text tipli mətn mesajı göndərir simli.

Təqdim olunan məlumat qane edən kiçik bir server söhbətini həyata keçirmək üçün kifayətdir texniki tapşırıqlar: internet_sockets.doc (Word Doc 97-2003, 26.5 Kb).

Bu məqalə 10 oktyabr 2010-cu il, bazar günü, saat 1:24-də bölmədə yazılmışdır. Siz məqaləyə şərhlərin yeniləmələrinə abunə ola bilərsiniz -. Bacararsan


Giriş


Bu məqalə Borland Delphi-də soket əsaslı müştəri/server proqramlarının yaradılması haqqındadır ("soketlər" - yuvalar). Soketlər mövzusunda əvvəlki məqalədən fərqli olaraq, burada biz server proqramlarının yaradılmasını təhlil edəcəyik.

Dərhal qeyd etmək lazımdır ki, ayrı-ayrı müştəri və server proqramlarının birgə mövcudluğu üçün bir neçə kompüterə sahib olmaq lazım deyil. Həm serveri, həm də müştərini eyni anda işlədə biləcəyiniz yalnız birinin olması kifayətdir. Bu halda, siz qoşulmaq istədiyiniz kompüterin adı kimi host adını istifadə etməlisiniz. localhost və ya IP ünvanı - 127.0.0.1 .

Beləliklə, nəzəriyyədən başlayaq. Əgər siz sadiq praktikantsınızsa (və gözlərinizlə heç bir alqoritm görə bilmirsinizsə), onda bu bölməni atlamalısınız.

Soket server alqoritmi


Soket server nə edir?.. Necə işləyir?.. Soket protokoluna əsaslanan server eyni anda bir çox müştəriyə xidmət göstərməyə imkan verir. Üstəlik, onların sayına özünüz limit təyin edə bilərsiniz (və ya standart olaraq olduğu kimi bu limiti tamamilə aradan qaldırın). Hər bir qoşulmuş müştəri üçün server ayrıca bir yuva açır, onun vasitəsilə müştəri ilə məlumat mübadiləsi edə bilərsiniz. Həm də əla bir həll hər bir əlaqə üçün ayrıca bir proses (Thread) yaratmaqdır.

Aşağıda Delphi proqramlarında rozetka serverinin necə işləməsinə nümunə verilmişdir:

Sxemi daha ətraflı təhlil edək:

  • Port və Server Tipində xassələrin müəyyən edilməsi - müştərilərin serverə normal qoşulması üçün serverin istifadə etdiyi port müştərinin istifadə etdiyi portla tam uyğun olmalıdır (və əksinə). ServerType xassəsi əlaqə növünü müəyyən edir (ətraflı məlumat üçün aşağıya baxın);
  • rozetkanın açılması - Rozetin və göstərilən portun açılması. Burada müştərilərin qoşulmasını gözləməyin avtomatik başlaması həyata keçirilir ( Dinləmək);
  • Müştəri ilə əlaqə qurmaq və onunla məlumat mübadiləsi aparmaq - burada müştəri əlaqə qurur və onunla məlumat mübadiləsi aparılır. Bu mərhələ haqqında daha sonra bu məqalədə və sockets (müştəri tərəfi) haqqında məqalədə daha çox məlumat əldə edə bilərsiniz;
  • Müştərinin deaktiv edilməsi - Burada müştəri əlaqəni kəsir və onun serverlə rozetka əlaqəsi bağlanır;
  • Serverin və soketin bağlanması - Administratorun əmri ilə server öz işini dayandırır, bütün açıq soket kanallarını bağlayır və müştəri əlaqələrini gözləməyi dayandırır.

Qeyd etmək lazımdır ki, 3-4-cü nöqtələr dəfələrlə təkrarlanır, yəni. bu elementlər hər yeni müştəri bağlantısı üçün icra olunur.

Qeyd : Hal-hazırda Delphi-də rozetkalar haqqında çox az sənəd var, ona görə də bu mövzunu mümkün qədər dərindən öyrənmək istəyirsinizsə, onda mən sizə Unix/Linux sistemləri üzrə ədəbiyyat və elektron sənədlərə nəzər salmağı məsləhət görürəm - orada çox Sockets ilə iş nəzəriyyəsi yaxşı təsvir edilmişdir. Bundan əlavə, bu ƏS-lər üçün soket tətbiqlərinin bir çox nümunəsi var (lakin əsasən C/C++ və Perl-də).

TServerSocket komponentinin qısa təsviri


Burada tanış olacağıq əsas komponentin xassələri, üsulları və hadisələri TServerSocket.

Xüsusiyyətlər

Soket - açıq soket kanallarına çıxışınız olan TServerWinSocket sinfi. Sonra, bu əmlakı daha ətraflı nəzərdən keçirəcəyik, çünki. əslində əsas olanlardan biridir. Növ: TServerWinSocket ;
Server növü - server növü. İki dəyərdən birini qəbul edə bilər: stNonBlocking- müştəri yuvaları ilə sinxron iş. Bu tip serverlərlə siz hadisələr vasitəsilə müştərilərlə işləyə bilərsiniz OnClientReadOnClientWrite. stThreadBlocking- asinxron tip. Hər bir müştəri yuvası kanalı üçün ayrıca proses (Thread) yaradılır. Növ: TServerType ;
ThreadCacheSize - server tərəfindən keşlənəcək müştəri proseslərinin (Mövzu) sayı. Burada serverinizdəki yükdən asılı olaraq orta dəyəri seçməlisiniz. Keşləmə hər dəfə ayrı bir proses yaratmamaq və qapalı rozetkanı öldürməmək, daha sonra istifadə üçün buraxmaq üçün baş verir. Növ: Tam ;
Aktiv - serverin hazırda aktiv olub-olmamasının göstəricisi. Bu, əslində dəyərdir Doğru serverin işlədiyini və müştəriləri qəbul etməyə hazır olduğunu göstərir və Yalan- server söndürülüb. Serveri işə salmaq üçün sadəcə olaraq bu xüsusiyyəti təyin etməlisiniz Doğru. Növ: Boolean ;
liman - müştərilərlə əlaqə yaratmaq üçün port nömrəsi. Server və müştərilərdəki port eyni olmalıdır. 1025-dən 65535-ə qədər olan dəyərlər tövsiyə olunur 1-dən 1024-ə qədər - sistem tərəfindən işğal edilə bilər. Növ: Tam ;
Xidmət - xidməti təyin edən sətir ( ftp, http, pop və s.) kimin portu istifadə olunacaq. Bu, port nömrələrini müxtəlif standart protokollara uyğunlaşdırmaq üçün bir növ istinad kitabıdır. Növ: simli ;

açıq - Serveri işə salır. Əslində, bu əmr dəyər təyin etməklə eynidir Doğruəmlak Aktiv;
yaxın - Serveri dayandırır. Əslində, bu əmr dəyər təyin etməklə eynidir Yalanəmlak Aktiv.

OnClientConnect - müştəri soket bağlantısı qurduqda və serverdən cavab gözlədikdə baş verir ( OnAccept);
OnClientDisconnect - müştərinin rozetka kanalından ayrılması zamanı baş verir;
OnClient Error - cari əməliyyat uğursuz olduqda baş verir, yəni. Bir səhv baş verdi;
OnClientRead - müştəri bəzi məlumatları serverə göndərdikdə baş verir. Bu məlumatlara ötürülən parametr vasitəsilə daxil olmaq olar Soket: TCustomWinSocket;
OnClientWrite - server soketdə müştəriyə məlumat göndərə bildikdə baş verir;
OnGetSocket - bu hadisənin idarəedicisində parametri redaktə edə bilərsiniz ClientSocket;
OnGetThread - bu hadisənin idarəedicisində parametr təyin etməklə hər bir müştəri kanalı üçün unikal proses (Mövzu) təyin edə bilərsiniz. SocketThread istədiyiniz alt tapşırıq TServerClientThread;
OnThreadStart , OnThreadEnd - müvafiq olaraq alt tapşırıq (proses, Thread) başlayanda və ya dayandıqda baş verir;
OnAccept - server müştəri qəbul etdikdə və ya əlaqədən imtina etdikdə baş verir;
OnListen - Server müştərilərin qoşulmasını gözləmə rejiminə daxil olduqda baş verir.


TServerSocket.Socket(TServerWinSocket)


Beləliklə, bir server müştəriyə məlumat göndərə bilər? Məlumatların qəbulu haqqında nə demək olar? Əsasən hadisələr üzərində işləsəniz OnClientReadOnClientWrite, sonra siz ClientSocket (TCustomWinSocket) parametri vasitəsilə müştəri ilə əlaqə saxlaya bilərsiniz. Bu siniflə işləmək haqqında müştəri yuvaları haqqında məqalədə oxuya bilərsiniz. bu sinif vasitəsilə məlumatların göndərilməsi/göndərilməsi oxşardır - üsullar (Göndər/Qəbul) (Mətn, Bufer, Axın). Həmçinin TServerSocket.Socket ilə işləyərkən. Lakin, o vaxtdan Bir serveri nəzərdən keçirdiyimiz üçün bəzi faydalı xüsusiyyətlər və üsullar vurğulanmalıdır:

  • ActiveConnections (Tam) - qoşulmuş müştərilərin sayı;
  • Active Threads (Tam) işləyən proseslərin sayıdır;
  • Əlaqələr (massiv) hər bir bağlı müştəri üçün fərdi TClientWinSocket siniflərindən ibarət massivdir. Məsələn, bu əmr:
    ServerSocket1.Socket.Connections.SendText("Salam!");
    ilk qoşulan müştəriyə "Salam!" mesajı göndərir. Bu massivin elementləri ilə işləmək üçün əmrlər də (Göndər/Qəbul)(Mətn,Bufer, Axın);
  • Idle Threads (Tam) sərbəst proseslərin sayıdır. Bu cür proseslər server tərəfindən keşlənir (bax ThreadCacheSize);
  • yerli ünvan, localhost, yerli liman- müvafiq olaraq - yerli IP ünvanı, host adı, port;
  • uzaq ünvan, uzaq host, uzaq port- müvafiq olaraq - uzaq IP ünvanı, host adı, port;
  • Metodlar bağlamaqkilidini açın- müvafiq olaraq, bir rozetkanın bloklanması və blokdan çıxarılması.

Təcrübə və nümunələr


İndi yuxarıdakıları nəzərdən keçirin konkret misal. Hazır mənbələri klikləməklə yükləyə bilərsiniz.

Beləliklə, TServerSocket ilə işləməyin çox yaxşı bir nümunəsinə baxaq (bu nümunə bu komponenti öyrənmək üçün ən əyani yardımdır). Aşağıdakı mənbə kodu bütün mühüm server hadisələrinin qeydiyyatını, həmçinin qəbul və göndərmə qabiliyyətini nümayiş etdirir mətn mesajları:

Misal 1 Giriş və təhsil server işi, rozetkalar vasitəsilə mesajların göndərilməsi/qəbul edilməsi

(... Burada fayl başlığı və TForm1 formasının tərifi və onun Form1 nümunəsi gəlir)
(Tam mənbəyə baxın)
prosedur TForm1.Button1Click(Sender: TObject); başlamaq (Limanı təyin edirik və serveri işə salırıq) ServerSocket1.Port:= 1025; (Daxil et metodu müəyyən edilmiş mövqedə seriala sətir daxil edir) Memo2.Lines.Insert(0,"Server başlayır"); ServerSocket1.Open; son; prosedur TForm1.Button2Click(Sender: TObject); başlamaq (Serveri dayandırın) ServerSocket1.Active:= Yanlış; Memo2.Lines.Insert(0,"Server dayandı"); son; proseduru TForm1.ServerSocket1Listen(Sender: TObject; Socket: TCustomWinSocket); başlamaq (Burada server müştərilər üçün rozetkada "dinləyir") Memo2.Lines.Insert(0,"Listening on port "+IntToStr(ServerSocket1.Port)); son; prosedur TForm1.ServerSocket1Accept(Sender: TObject; Socket: TCustomWinSocket); başlamaq (Burada server müştəri qəbul edir) Memo2.Lines.Insert(0,"Müştəri bağlantısı qəbul edildi"); son; prosedur TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); başlamaq (Burada müştəri bağlanır) Memo2.Lines.Insert(0,"Müştəri qoşulub"); son; prosedur TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); başlamaq (Burada müştəri əlaqəni kəsir) Memo2.Lines.Insert(0,"Müştəri əlaqəsi kəsildi"); son; prosedur TForm1.ServerSocket1ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TERrorEvent; var ErrorCode: Integer); başlamaq (Xəta baş verdi - kodunu çap edin) Memo2.Lines.Insert(0,"Müştəri xətası. Kod = "+IntToStr(ErrorCode)); son; prosedur TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); başlamaq (Müştəridən mesaj alındı ​​- onu Memo1-də göstəririk) Memo2.Lines.Insert(0,"Müştəridən mesaj alındı"); Memo1.Lines.Insert(0,"> "+Socket.ReceiveText); son; prosedur TForm1.ServerSocket1ClientWrite(Sender: TObject; Socket: TCustomWinSocket); başlamaq (İndi siz məlumatı rozetkaya göndərə bilərsiniz) Memo2.Lines.Insert(0,"İndi rozetkaya yaza bilər"); son; prosedur TForm1.ServerSocket1GetSocket(Sender: TObject; Socket: Integer; var ClientSocket: TServerClientWinSocket); start Memo2.Lines.Insert(0,"Get rozetka"); son; prosedur TForm1.ServerSocket1GetThread(Göndərən: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); start Memo2.Lines.Insert(0,"Mövzu alın"); son; prosedur TForm1.ServerSocket1ThreadEnd(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"Mövzu sonu"); son; prosedur TForm1.ServerSocket1ThreadStart(Sender: TObject; Thread: TServerClientThread); begin Memo2.Lines.Insert(0,"Mövzu başlanğıcı"); son; prosedur TForm1.Button3Click(Sender: TObject); var i: Tam ədəd; başlamaq (BÜTÜN müştərilərə Edit1-dən mesaj göndərin) i üçün:= 0-dan ServerSocket1.Socket.ActiveConnections-1 başlayır ServerSocket1.Socket.Connections[i].SendText(Edit1.Text); son; Memo1.Lines.Insert(0,"

TServerSocket ilə işləmək üsulları (və sadəcə rozetkalar)


Hər bir müştəri üçün unikal məlumatların saxlanması.


Şübhəsiz ki, əgər serveriniz bir çox müştəriyə xidmət göstərəcəksə, onda siz hər bir müştəri üçün bəzi məlumatları (ad və s.) saxlamalı və bu məlumatı bu müştərinin yuvasına bağlamalısınız. Bəzi hallarda, bütün bunları əl ilə etmək (rozetka sapına bağlama, müştərilərin massivləri və s.) çox rahat deyil. Buna görə də, hər bir yuva üçün xüsusi bir xüsusiyyət var - Data. Əslində, Data sadəcə bir göstəricidir. Buna görə də, müştəri məlumatlarını bu xüsusiyyətə yazarkən diqqətli olun və göstəricilərlə işləmə qaydalarına əməl edin (yaddaşın ayrılması, tipin çıxarılması və s.)!

Faylların rozetka üzərindən göndərilməsi.


Burada faylları rozetka vasitəsilə göndərməyə baxacağıq (JINX tərəfindən tələb olunduğu kimi) :-). Beləliklə, bir rozetka üzərindən faylı necə göndərmək olar? Çox sadə! Siz sadəcə olaraq bu faylı fayl axını (TFileStream) kimi açmalı və onu rozetka (SendStream) vasitəsilə göndərməlisiniz! Buna bir misalla baxaq:

Qeyd etmək lazımdır ki, üsul göndərmə axını yalnız server tərəfindən deyil, həm də müştəri tərəfindən istifadə olunur ( ClientSocket1.Socket.SendStream(srcfile))

Nə üçün ötürmə zamanı bir neçə blok bir blokda birləşdirilə bilər?


Bu da JINX tərəfindən tələb olunur :-). Bunun üçün ona çox sağ olun! Beləliklə, ilk növbədə qeyd etmək lazımdır ki, rozetka vasitəsilə göndərilən məlumatlar yalnız bir blokda birləşdirilə bilməz, həm də bir neçə bloka ayrıla bilər. Fakt budur ki, rozetka normal axındır, lakin məsələn, fayl axınından (TFileStream) fərqli olaraq, məlumatları daha yavaş ötürür (başa düşürsünüz - şəbəkə, məhdud trafik və s.). Buna görə də iki əmr:
ServerSocket1.Socket.Connections.SendText("Salam,");
ServerSocket1.Socket.Connections.SendText("dünya!");
bir əmrlə tamamilə eynidir:
ServerSocket1.Socket.Connections.SendText("Salam, dünya!");

Buna görə də, əgər siz rozetka vasitəsilə məsələn, 100 Kb fayl göndərsəniz, bu bloku göndərdiyiniz şəxs trafikdən və xətt yükündən asılı olan ölçüləri olan bir neçə blok alacaq. Üstəlik, ölçülərin eyni olması lazım deyil. Bundan belə nəticə çıxır ki, fayl və ya hər hansı digər məlumatı almaq üçün böyük ölçü, Siz məlumat bloklarını götürməli və sonra onları bir bütövlükdə birləşdirməlisiniz (və məsələn, faylda saxlamalısınız). Bu problemin əla həlli eyni fayl axınıdır - TFileStream (və ya yaddaşdakı axın - TMemoryStream). Siz universal metoddan istifadə edərək OnRead (OnClientRead) hadisəsi vasitəsilə soketdən məlumat hissəciklərini qəbul edə bilərsiniz. ReceiveBuf. Metoddan istifadə edərək yaranan blokun ölçüsünü təyin edə bilərsiniz Qəbul Uzunluğu. Siz həmçinin rozetka axınından istifadə edə bilərsiniz (TClientSocket məqaləsinə baxın). Və burada kiçik bir nümunə (təxmini):

Soketə necə nəzarət etmək olar


Bu məsələ mürəkkəbdir və uzun müddət nəzərdən keçirilməsini tələb edir. Hələlik yalnız qeyd edəcəm ki, siz həmişə proqramınızın yaratdığı yuvaya nəzarət edə bilərsiniz :-). Soketlərin (Windows-dakı əksər obyektlər kimi) Handle xassəsində yazılmış öz tutacağı (tutacağı) var. Beləliklə, bu deskriptoru öyrənərək, hər hansı bir rozetkanı (hətta başqasının proqramı tərəfindən yaradılanları) sərbəst idarə edə bilərsiniz! Bununla belə, başqasının yuvasına nəzarət etmək üçün çox güman ki, WinAPI Sockets funksiyalarından istifadə etməli olacaqsınız.


Bu məqalə Delphi-də TServerSocket komponenti ilə işləmək üçün əsas fəndləri və rozetkalar üzərindən ünsiyyət üçün bir neçə ümumi fəndləri göstərir. Hər hansı bir sualınız varsa, onları mənə elektron poçtla göndərin: [email protected], və daha yaxşısı - bu saytın forumunda (Delphi. Ümumi suallar) yazın ki, digər istifadəçilər sualınızı görüb cavab verməyə çalışsınlar!

Karix Nikolay ( Nitro). Moskva vilayəti, Jukovski

Bu məqalə Borland Delphi-də soket əsaslı müştəri/server proqramlarının yaradılması haqqındadır. Soketlər mövzusunda əvvəlki məqalədən fərqli olaraq, burada biz server proqramlarının yaradılmasını təhlil edəcəyik.
Dərhal qeyd etmək lazımdır ki, ayrı-ayrı müştəri və server proqramlarının birgə mövcudluğu üçün bir neçə kompüterə sahib olmaq lazım deyil. Həm serveri, həm də müştərini eyni anda işlədə biləcəyiniz yalnız birinin olması kifayətdir. Bu halda, siz qoşulmaq istədiyiniz kompüterin adı kimi localhost host adını və ya IP ünvanını - 127.0.0.1 istifadə etməlisiniz.
Beləliklə, nəzəriyyədən başlayaq. Əgər siz sadiq praktikantsınızsa (və gözlərinizlə heç bir alqoritm görə bilmirsinizsə), onda bu bölməni atlamalısınız.
Soket server alqoritmi
Soket server nə edir?.. Necə işləyir?.. Soket protokoluna əsaslanan server eyni anda bir çox müştəriyə xidmət göstərməyə imkan verir. Üstəlik, onların sayına özünüz limit təyin edə bilərsiniz (və ya standart olaraq olduğu kimi bu limiti tamamilə aradan qaldırın). Hər bir qoşulmuş müştəri üçün server ayrıca bir yuva açır, onun vasitəsilə müştəri ilə məlumat mübadiləsi edə bilərsiniz. Həm də əla bir həll hər bir əlaqə üçün ayrıca bir proses (Thread) yaratmaqdır.
Aşağıda Delphi proqramlarında rozetka serverinin necə işləməsinə nümunə verilmişdir:

Gəlin sxemə daha ətraflı nəzər salaq: · Port və ServerType xassələrinin tərifi - müştərilərin serverə normal qoşulması üçün serverin istifadə etdiyi port müştərinin istifadə etdiyi portla tam uyğun olmalıdır (və əksinə). ). ServerType xassəsi əlaqə növünü müəyyən edir (ətraflı məlumat üçün aşağıya baxın); · Açıq rozetka - açıq rozetka və müəyyən edilmiş port. Burada müştərilərin qoşulmasını gözləməyin avtomatik başlaması (Dinlə) həyata keçirilir; · Müştərinin qoşulması və onunla məlumat mübadiləsi - burada müştəri qoşulur və onunla məlumat mübadiləsi aparılır. Bu mərhələ haqqında daha sonra bu məqalədə və sockets (müştəri tərəfi) haqqında məqalədə daha çox məlumat əldə edə bilərsiniz; · Client Disconnect - Burada müştərinin əlaqəsi kəsilir və onun serverlə rozetka bağlantısı bağlanır; · Serverin və soketin bağlanması - Administratorun əmri ilə server bağlanır, bütün açıq soket kanallarını bağlayır və müştəri əlaqələrini gözləməyi dayandırır.
Qeyd etmək lazımdır ki, 3-4-cü nöqtələr dəfələrlə təkrarlanır, yəni. bu elementlər hər yeni müştəri bağlantısı üçün icra olunur.
Qeyd: Hal-hazırda Delphi-də rozetkalar haqqında çox az sənəd var, ona görə də bu mövzunu mümkün qədər dərindən öyrənmək istəyirsinizsə, sizə Unix/Linux sistemləri üzrə ədəbiyyat və elektron sənədlərə - işləmə nəzəriyyəsinə nəzər salmağı məsləhət görürəm. sockets orada çox yaxşı təsvir edilmişdir. Bundan əlavə, bu ƏS-lər üçün soket tətbiqlərinin bir çox nümunəsi var (lakin əsasən C/C++ və Perl-də).
TServerSocket komponentinin qısa təsviri
Burada komponentin əsas xassələri, üsulları və hadisələri ilə tanış olacağıq.
Xüsusiyyətlər
Socket - TServerWinSocket sinfi, onun vasitəsilə açıq soket kanallarına çıxışınız var. Sonra, bu əmlakı daha ətraflı nəzərdən keçirəcəyik, çünki. əslində əsas olanlardan biridir. Növ: TServerWinSocket;
ServerType - server növü. İki dəyərdən birini qəbul edə bilər: stNonBlocking - müştəri yuvaları ilə sinxron iş. Bu tip serverlə siz OnClientRead və OnClientWrite hadisələri vasitəsilə müştərilərlə işləyə bilərsiniz. stThreadBlocking asinxron tipdir. Hər bir müştəri yuvası kanalı üçün ayrıca proses (Thread) yaradılır. Növ: TServerType;
ThreadCacheSize - server tərəfindən keşlənəcək müştəri proseslərinin (Thread) sayı. Burada serverinizdəki yükdən asılı olaraq orta dəyəri seçməlisiniz. Keşləmə hər dəfə ayrı bir proses yaratmamaq və qapalı rozetkanı öldürməmək, daha sonra istifadə üçün buraxmaq üçün baş verir. Növ: Tam ədəd;
Aktiv - serverin hazırda aktiv olub-olmamasının göstəricisi. Yəni əslində True dəyəri serverin işlədiyini və müştəriləri qəbul etməyə hazır olduğunu, False isə serverin söndürüldüyünü göstərir. Serveri işə salmaq üçün sadəcə olaraq bu xüsusiyyəti True olaraq təyin etməlisiniz. Növ: Boolean
Port - müştərilərlə əlaqə yaratmaq üçün port nömrəsi. Server və müştərilərdəki port eyni olmalıdır. 1025-dən 65535-ə qədər olan dəyərlər tövsiyə olunur 1-dən 1024-ə qədər - sistem tərəfindən işğal edilə bilər. Növ: Tam ədəd;
Xidmət - portundan istifadə ediləcək xidməti (ftp, http, pop və s.) təyin edən sətir. Bu, port nömrələrini müxtəlif standart protokollara uyğunlaşdırmaq üçün bir növ istinad kitabıdır. Növ: simli
Metodlar
Açıq - Serveri işə salır. Əsasən, bu əmr Active xassəsinə True dəyərinin təyin edilməsi ilə eynidir;
Bağla - Serveri dayandırır. Əsasən, bu əmr Active xassəsinə False dəyərini təyin etməklə eynidir.
İnkişaflar
OnClientConnect - müştəri soket bağlantısı qurduqda və serverin cavabını gözlədikdə baş verir (OnAccept);
OnClientDisconnect - Müştəri soket kanalından ayrıldıqda qaldırılır.
OnClientError - Cari əməliyyat uğursuz olduqda qaldırılır, yəni. Bir səhv baş verdi;
OnClientRead - müştəri bəzi məlumatları berverə göndərdikdə işə salınır. Bu məlumatı təchiz edilmiş Socket parametri vasitəsilə əldə etmək olar: TCustomWinSocket;
OnClientWrite - server soketdəki müştəriyə məlumat göndərə bildikdə baş verir;
OnGetSocket - bu hadisə idarəedicisində siz ClientSocket parametrini redaktə edə bilərsiniz;
OnGetThread - bu hadisənin idarəedicisində siz SocketThread parametrinə tələb olunan TServerClientThread alt tapşırığını təyin etməklə hər bir ayrıca müştəri kanalı üçün unikal prosesi (Thread) təyin edə bilərsiniz;
OnThreadStart, OnThreadEnd - müvafiq olaraq alt tapşırıq (proses, Thread) başlayanda və ya dayandıqda baş verir;
OnAccept - server müştəri ilə əlaqəni qəbul etdikdə və ya rədd etdikdə işə salınır;
OnListen - Server müştərilərin qoşulmasını gözlədikdə qaldırılır.
TServerSocket.Socket(TServerWinSocket)
Beləliklə, bir server müştəriyə məlumat göndərə bilər? Məlumatların qəbulu haqqında nə demək olar? Əsasən, OnClientRead və OnClientWrite hadisələri ilə işləyirsinizsə, onda siz ClientSocket (TCustomWinSocket) parametri vasitəsilə müştəri ilə əlaqə saxlaya bilərsiniz. Bu siniflə işləmək haqqında müştəri yuvaları haqqında məqalədə oxuya bilərsiniz. bu sinif vasitəsilə məlumatların göndərilməsi/göndərilməsi oxşardır - üsullar (Göndər/Qəbul) (Mətn, Bufer, Axın). Həmçinin TServerSocket.Socket ilə işləyərkən. Lakin, o vaxtdan burada bir serveri nəzərdən keçiririk, bəzi faydalı xüsusiyyətlər və üsullar vurğulanmalıdır: ActiveConnections (Integer) - qoşulmuş müştərilərin sayı; ActiveThreads (Integer) - işləyən proseslərin sayı; ·Bağlantılar (massiv) - hər bir qoşulmuş müştəri üçün ayrıca TClientWinSocket siniflərindən ibarət massiv. Məsələn, aşağıdakı əmr: ServerSocket1.Socket.Connections.SendText("Salam!"); İlk qoşulmuş müştəriyə "Salam!" mesajı göndərir. Bu massivin elementləri ilə işləmək üçün əmrlər də (Göndər/Qəbul)(Mətn,Bufer, Axın); ·IdleThreads (Integer) - boş proseslərin sayı. Bu cür proseslər server tərəfindən keşlənir (bax ThreadCacheSize); LocalAddress, LocalHost, LocalPort - müvafiq olaraq - yerli IP ünvanı, host adı, port; ·RemoteAddress, RemoteHost, RemotePort - müvafiq olaraq - uzaq IP ünvanı, host adı, port; ·Methods Lock and Unlock - müvafiq olaraq, rozetkanın bloklanması və blokdan çıxarılması.
Təcrübə və nümunələr
İndi isə konkret misalla yuxarıdakılara nəzər salaq. Hazır mənbələri buraya klikləməklə yükləyə bilərsiniz.
Beləliklə, TServerSocket ilə işləməyin çox yaxşı bir nümunəsinə baxaq (bu nümunə bu komponenti öyrənmək üçün ən əyani yardımdır). Aşağıdakı mənbələr bütün mühüm server hadisələrinin qeydini, həmçinin mətn mesajlarını qəbul etmək və göndərmək qabiliyyətini nümayiş etdirir:
Misal 1. Serverin işini qeyd etmək və öyrənmək, rozetkalar vasitəsilə mesajların göndərilməsi/qəbul edilməsi.

(... Burada fayl başlığı və TForm1 formasının tərifi və onun Form1 nümunəsi gəlir)

(Tam mənbəyə burada baxın)

prosedur TForm1.Button1Click (Göndərən: TObject );

başlamaq

(Limanı təyin edirik və serveri işə salırıq)

ServerSocket1.Port := 1025 ;

(Daxil et metodu müəyyən edilmiş mövqedə seriala sətir daxil edir)

Memo2.Lines .Insert (0 ,"Server starting" );

ServerSocket1.Open ;

son;

prosedur TForm1.Button2Click (Göndərən: TObject );

başlamaq

(Serveri dayandırın)

ServerSocket1.Active := Yanlış ;

Memo2.Lines .Daxil et (0 ,"Server dayandı" );

son;

proseduru TForm1.ServerSocket1Listen(Göndərən: TObject ;

Soket: TCustomWinSocket);

başlamaq

(Burada server müştərilər üçün rozetkada "dinləyir")

Memo2.Lines .Daxil edin (0 ,"Listening on port " +IntToStr (ServerSocket1.Port ) );

son;

prosedur TForm1.ServerSocket1Accept(Sender: TObject ;

Soket: TCustomWinSocket);

başlamaq

(Burada server müştəri qəbul edir)

Memo2.Lines .Daxil edin (0 ,"Müştəri bağlantısı qəbul edildi" );

son;

prosedur TForm1.ServerSocket1ClientConnect(Göndərən: TObject ;

Soket: TCustomWinSocket);

başlamaq

(Burada müştəri bağlanır)

Memo2.Lines .Daxil et (0 ,"Müştəri qoşuldu" );

son;

prosedur TForm1.ServerSocket1ClientDisconnect(Göndərən: TObject ;

Soket: TCustomWinSocket);

başlamaq

(Burada müştəri əlaqəni kəsir)

Memo2.Lines .Daxil et (0 ,"Müştəri əlaqəsi kəsildi" );

son;

prosedur TForm1.ServerSocket1ClientError (Göndərən: TObject ;

Soket: TCustomWinSocket; ErrorEvent: TERrorEvent;

var ErrorCode: Integer);

başlamaq

(Xəta baş verdi - kodunu çap edin)

Memo2.Lines .Daxil edin (0 ,"Müştəri xətası. Kod = " +IntToStr (Xəta Kodu) );

son;

prosedur TForm1.ServerSocket1ClientRead(Göndərən: TObject ;

Soket: TCustomWinSocket);

başlamaq

(Müştəridən mesaj alındı ​​- onu Memo1-də göstəririk)

Memo2.Lines .Daxil et (0 , "Müştəridən mesaj alındı") ;

Memo1.Lines .Insert (0 ,"> " +Socket.ReceiveText );

son;

prosedur TForm1.ServerSocket1ClientWrite(Göndərən: TObject ;

Soket: TCustomWinSocket);

başlamaq

(İndi siz məlumatı rozetkaya göndərə bilərsiniz)

Memo2.Lines .Daxil et (0 ,"İndi rozetkaya yaza bilər" );

son;

proseduru TForm1.ServerSocket1GetSocket (Göndərən: TObject ; Socket: Integer ;

var ClientSocket: TServerClientWinSocket);

başlamaq

Memo2.Lines .Insert (0 ,"Get rozetka" );

son;

prosedur TForm1.ServerSocket1GetThread(Göndərən: TObject ;

ClientSocket: TServerClientWinSocket;

varSocketThread: TServerClientThread);

başlamaq

Memo2.Lines .Insert (0 ,"Get Thread" );

son;

prosedur TForm1.ServerSocket1ThreadEnd (Göndərən: TObject ;

başlamaq

Memo2.Lines .Daxil et (0 ,"Mövzu sonu" );

son;

prosedur TForm1.ServerSocket1ThreadStart(Göndərən: TObject ;

Mövzu: TServerClientThread);

başlamaq

Memo2.Lines .Daxil et (0 ,"Mövzu başlanğıcı" );

son;

prosedur TForm1.Button3Click (Göndərən: TObject );

var i: Integer ;

başlamaq

(BÜTÜN müştərilərə Edit1-dən mesaj göndərin)

i:= 0 üçün ServerSocket1.Socket.ActiveConnections -1 başlayır

ServerSocket1.Socket .Bağlantılar [i] .SendText (Edit1.Text ) ;

son;

Memo1.Lines .Insert(0 ,"< " +Edit1.Text ) ;

son;

Bundan əlavə, biz artıq nümunələri deyil, TServerSocket ilə işləmə üsullarını nəzərdən keçirəcəyik.
TServerSocket ilə işləmək üsulları (və sadəcə rozetkalar)
Hər bir müştəri üçün unikal məlumatların saxlanması.
Şübhəsiz ki, əgər serveriniz bir çox müştəriyə xidmət göstərəcəksə, onda siz hər bir müştəri üçün bəzi məlumatları (ad və s.) saxlamalı və bu məlumatı bu müştərinin yuvasına bağlamalısınız. Bəzi hallarda, bütün bunları əl ilə etmək (rozetka sapına bağlama, müştərilərin massivləri və s.) çox rahat deyil. Buna görə də, hər bir yuva üçün xüsusi bir xüsusiyyət var - Data. Əslində, Data sadəcə bir göstəricidir. Buna görə də, müştəri məlumatlarını bu xüsusiyyətə yazarkən diqqətli olun və göstəricilərlə işləmə qaydalarına əməl edin (yaddaşın ayrılması, tipin çıxarılması və s.)!
Faylların rozetka üzərindən göndərilməsi.
Burada faylları rozetka vasitəsilə göndərməyə baxacağıq (JINX tərəfindən tələb olunduğu kimi) :-). Beləliklə, bir rozetka üzərindən faylı necə göndərmək olar? Çox sadə! Siz sadəcə olaraq bu faylı fayl axını (TFileStream) kimi açmalı və onu rozetka (SendStream) vasitəsilə göndərməlisiniz! Buna bir misalla baxaq:

(Fayl rozetka üzərindən göndərilir)

prosedur SendFileBySocket(fayl adı: string );

var srcfile: TFileStream;

başlamaq

(Fayl adını açın)

Srcfile:= TFileStream.Create (fayl adı, fmOpenRead) ;

(Onu ilk qoşulan müştəriyə göndərin)

ServerSocket1.Socket .Bağlantılar [ 0 ] .SendStream(srcfile) ;

(Faylı bağlayın)

Srcfile.Free ;

son;

Qeyd etmək lazımdır ki, SendStream metodu yalnız server tərəfindən deyil, həm də müştəri tərəfindən istifadə olunur (ClientSocket1.Socket.SendStream(srcfile))
Nə üçün ötürmə zamanı bir neçə blok bir blokda birləşdirilə bilər?
Bu da JINX tərəfindən tələb olunur :-). Bunun üçün ona çox sağ olun! Beləliklə, ilk növbədə qeyd etmək lazımdır ki, rozetka vasitəsilə göndərilən məlumatlar yalnız bir blokda birləşdirilə bilməz, həm də bir neçə bloka ayrıla bilər. Fakt budur ki, rozetka normal axındır, lakin məsələn, fayl axınından (TFileStream) fərqli olaraq, məlumatları daha yavaş ötürür (başa düşürsünüz - şəbəkə, məhdud trafik və s.). Buna görə də iki əmr:
ServerSocket1.Socket.Connections.SendText("Salam,");
ServerSocket1.Socket.Connections.SendText("dünya!");
bir əmrlə tamamilə eynidir:
ServerSocket1.Socket.Connections.SendText("Salam, dünya!");
Buna görə də, əgər siz rozetka vasitəsilə məsələn, 100 Kb fayl göndərsəniz, bu bloku göndərdiyiniz şəxs trafikdən və xətt yükündən asılı olan ölçüləri olan bir neçə blok alacaq. Üstəlik, ölçülərin eyni olması lazım deyil. Buradan belə nəticə çıxır ki, faylı və ya hər hansı digər böyük məlumatı qəbul etmək üçün verilənlər bloklarını qəbul etməli və sonra onları bir bütövlükdə birləşdirməlisiniz (və məsələn, faylda saxlamalısınız). Bu problemin əla həlli eyni fayl axınıdır - TFileStream (və ya yaddaşdakı axın - TMemoryStream). Siz ReceiveBuf universal metodundan istifadə edərək OnRead (OnClientRead) hadisəsi vasitəsilə soketdən məlumat hissəciklərini qəbul edə bilərsiniz. Alınan blokun ölçüsünü ReceiveLength metodundan istifadə edərək təyin edə bilərsiniz. Siz həmçinin rozetka axınından istifadə edə bilərsiniz (TClientSocket məqaləsinə baxın). Və burada kiçik bir nümunə (təxmini):

(Faylı rozetka üzərindən qəbul edin)

prosedur TForm1.ClientSocket1Read(Göndərən: TObject ;

Soket: TCustomWinSocket);

varl: Tam ədəd;

Buf: PChar ;

Src: TFileStream;

başlamaq

(Alınan blokun ölçüsünü l ilə yazırıq)

L:= Socket.ReceiveLength ;

(Bufer üçün yaddaş sifariş edirik)

GetMem (buf, l+1 );

(Alınan bloku buferə yazırıq)

Socket.ReceiveBuf(buf,l);

(Yazmaq üçün müvəqqəti fayl açın)

Src:= TFileStream.Create("myfile.tmp" ,fmOpenReadWrite) ;

(Mövqeni faylın sonuna qoyun)

Src.Seek(0,soFromEnd);

(Fayl üçün bufer yazın)

Src.WriteBuffer(buf,l);

(Faylı bağlayın)

Src.Free;

(Yaddaşın boşaldılması)

FreeMem (buf);

son;

Soketə necə nəzarət etmək olar
Bu məsələ mürəkkəbdir və uzun müddət nəzərdən keçirilməsini tələb edir. Hələlik yalnız qeyd edəcəm ki, siz həmişə proqramınızın yaratdığı yuvaya nəzarət edə bilərsiniz :-). Soketlərin (Windows-dakı əksər obyektlər kimi) Handle xassəsində yazılmış öz tutacağı (tutacağı) var. Beləliklə, bu deskriptoru öyrənərək, hər hansı bir rozetkanı (hətta başqasının proqramı tərəfindən yaradılanları) sərbəst idarə edə bilərsiniz! Bununla belə, başqasının yuvasına nəzarət etmək üçün çox güman ki, WinAPI Sockets funksiyalarından istifadə etməli olacaqsınız.
Epiloq
Bu məqalə Delphi-də TServerSocket komponenti ilə işləmək üçün əsas fəndləri və rozetkalar üzərindən ünsiyyət üçün bir neçə ümumi fəndləri göstərir. Hər hansı bir sualınız varsa, onları mənə elektron poçtla göndərin: [email protected], və daha yaxşısı - bu saytın forumunda (Delphi. Ümumi suallar) yazın ki, digər istifadəçilər sualınızı görüb cavab verməyə çalışsınlar!
Karix Nikolay (Nitro). Moskva vilayəti, Jukovski

Mən şəbəkə dəstəyi əlavə etdim. Bu ayrı server və ayrıca müştəri yaradılmışdır. Məsələ ondadır ki, proqram serveri işləyir, istifadəçi müştərini işə salır və sorğunu istifadəçiyə daxil edir: Moskva Tverskaya 6. Sonra server sorğunu emal edir, Yandex.Maps-dan axtarış nəticələrini alır və nəticədə yaranan şəkli müştəriyə göndərir. , sonra hissə istifadəçinin tələbinə uyğun gələn TMap komponent kartında müştəridə göstərilir. Nəticədə istifadəçi onu miqyaslandıra, saxlaya bilər və s.

Ona görə də bu yazıda sizə müştəri və serveri necə həyata keçirdiyimi söyləmək istəyirəm. Mən bunu TClientSocket və TServerSocket köməyi ilə etdim, bu məqalədə layihəmdə istifadə etdiyim üsulları ətraflı nəzərdən keçirəcəyik.

Əvvəlcə bu komponentlərin IDE-də necə quraşdırıla biləcəyinə baxaq. Əgər siz Delphi 7 IDE-dən istifadə edirsinizsə, deməli, bu komponentlər standart olaraq mövcuddur, lakin təəssüf ki, onlar quraşdırılmayıb, lakin bu problem deyil. Sadəcə Delphi-ni açıb quraşdırmaq lazımdır.

Bunun üçün Component-Install Packages... əmrini yerinə yetirin və görünən pəncərədə Əlavə et düyməsini sıxın. Bundan sonra, adətən standart olaraq BIN qovluğunda yerləşən dclsockets70.bpl faylına gedən yolu göstərməlisiniz. Bundan sonra OK düyməsini sıxmaq lazımdır. Hər şey, komponentləriniz İnternet nişanında görünməlidir (TClientSocket və TServerSocket).

Layihədə minimum server inkişafı ilə bütün işə başladım. Əvvəlcə formada TServerSocket komponentini quraşdırdım. Və Start server düyməsini klikləməklə, təyin edin ilkin parametrlər, onu işə salmaq üçün:

server. Port := FormServerSetting. SpinEditPort. dəyər; //server portunu təyin edin server. Aktiv := Doğrudur; // Serveri aktivləşdirin. açıq; ifServer. Aktiv sonra başlayın //serverin işlək vəziyyətdə olması barədə mesajı göstərin son; …….. //server işə salınmayıbsa, xətanı göstərin

Maşınımda serveri işə salmaq üçün mən yalnız pulsuz port (digər proqramlar tərəfindən tutulmayan) təyin etdim və onu aktivləşdirdim.

Prinsipcə, hamısı budur, iş üçün serverin işləməsi mənim üçün kifayət idi və mən onların göndərdiyi müştərilərin sorğularını emal edə bildim.

Serverə qoşulan müştərilərin siyahısını əldə etmək və onlarla daha da işləmək üçün mən TCheckListBox komponentini formada və TServerSocket komponentinin OnclientConnect hadisəsində quraşdırdım, aşağıdakı kodu yazdım:

TFormServer proseduru. ServerClientConnect (Göndərən: TObject; Soket: TCustomWinSocket); başlamaq //müştəri əlaqəsinə nəzarət edin zəngin editlog. SelAttributes. Rəng:=clYaşıl; zəngin editlog. SelAttributes. Üslub := [fsBold] ; CheckListClient. Əşyalar. Əlavə et(Socket.RemoteHost); zəngin editlog. Xətlər. Əlavə et ("[" + TimeToStr (Time ) + "] Müştəri qoşuldu: " + Socket. RemoteHost ); // qoşulmuş müştərini siyahıya əlavə edin zəngin editlog. İcra et(WM_VSCROLL, SB_BOTTOM, 0); son;

Yəni serverə qoşulan müştərilərin adlarını onlar haqqında əlavə məlumat əldə etmək üçün siyahıya əlavə edirəm.

Məsələn, ala bilərsiniz ətraflı məlumat müştəri haqqında:

TFormInfoClient proseduru. FormShow(Göndərən: TObject); başlamaq // müştəri haqqında məlumatı çap edin başlıq:= "Müştəri məlumatı:"+ forma server. CheckListClient. Elementlər [FormServer. CheckListClient. ItemIndex]; yerli ad. Başlıq:= FormServer. Server. rozetka. Əlaqələr [FormServer. CheckListClient. ItemIndex]. LocalHost; yerli ev sahibi. Başlıq:= FormServer. Server. rozetka. Əlaqələr [FormServer. CheckListClient. ItemIndex]. Yerli Ünvan; yerli liman. Başlıq := IntToStr (FormServer. Server. Socket. Əlaqələr [FormServer. CheckListClient. ItemIndex]. LocalPort); uzaq ad. Başlıq:= FormServer. Server. rozetka. Əlaqələr [FormServer. CheckListClient. ItemIndex]. uzaq host; uzaq ev sahibi. Başlıq:= FormServer. Server. rozetka. Əlaqələr [FormServer. CheckListClient. ItemIndex]. Uzaqdan Ünvan; uzaqdan port. Başlıq := IntToStr (FormServer. Server . Soket . Əlaqələr [ FormServer. CheckListClient . ItemIndex ] . RemotePort ); son;

Aşağıdakı məlumatları əldə edə bilərsiniz:

  • yerli ad
  • Yerli ünvan
  • yerli liman
  • uzaq ad
  • uzaq ünvan
  • uzaq port

TCheckListBox komponentinin siyahısında seçdiyim bu koddan istifadə edərək müştəri haqqında məlumat alıram.

Gördüyünüz kimi, mürəkkəb bir şey yoxdur, müştəriyə mesaj göndərmək üçün aşağıdakı kodu istifadə edə bilərsiniz:

AT kvadrat mötərizələr, mesajı hansı müştəriyə göndərəcəyimizi göstərirəm (bu, TCheckListBox komponentində seçilmiş müştəriyə bərabərdir), mesajda #message# qeyd edirəm - bu o deməkdir ki, bu serverdən gələn normal mesajdır, sadəcə olaraq pəncərədə göstərilir.

Müştəridən serverə mesaj almaq üçün bizə TServerSocket komponentinin OnClientRead hadisəsi və müştəri tərəfindən göndərilən sorğunu yazacağımız mətn dəyişəni lazımdır.

TFormServer proseduru. ServerClientRead(Göndərən: TObject; Soket: TCustomWinSocket); var query: String ; başlamaq //kart üçün müştəridən sorğu almaq sorğuya cəhd edin:= Socket. ReceiveText ; əgər pos("sorğu", sorğu)<>0 sonra başlayın //Yandex-dən sorğu və ya Google koordinatları müştərinin istəyinə uyğun olaraq kartlar son; //sadəcə müştəridən mesajdırsa, onu göstərin if pos("#message#", sorğu)<>0 sonra sona başlayın; ……

Bu koddan görə bilərsiniz ki, müştəri həm serverə adi mesaj, həm də kart tələbi göndərə bilər: Moskva, Tverskaya, 6.

Bunun üçün mən adi mesajın harada olduğunu və kartın alınması üçün sorğunun dəqiq harada olduğunu müəyyən etməliyəm ki, server gələcəkdə onu emal edə bilsin. Bu halda, ən başlanğıcda müştərinin mesajlarına aşağıdakı identifikatorları əlavə edirəm:

  • #mesaj#
  • #sorğu#

Əgər #message# identifikatoru müştərinin mesajının əvvəlində varsa, o zaman server onu müştərinin normal mesajı kimi tanıyacaq. Mesajın əvvəlində #query# identifikatoru varsa, bu o deməkdir ki, müştəri kart almaq üçün sorğu göndərib.

Həmçinin, müştəri istənilən vaxt serverlə əlaqəni kəsə bilər, biz də onu serverə qoşulmuş müştərilərin ümumi siyahısından çıxarmaq üçün bunu izləməliyik. Bunun üçün TServerSocket komponentini seçin və OnClientDisconnect hadisəsinə aşağıdakı kodu yazın:

TFormServer proseduru. ServerClientDisconnect (Göndərən: TObject; Soket: TCustomWinSocket); var i: integer ; cəhd etməyə başlayın //müştəri bağlanmasına nəzarət edin zəngin editlog. SelAttributes. Rəng:=clRed; zəngin editlog. SelAttributes. Üslub := [fsBold] ; i üçün := 0 Serverə. rozetka. ActiveConnections - Server olduqda 1 başlayır. rozetka. Əlaqələr[i]. Dəstək = server. rozetka. Əlaqələr[i]. İdarə edin, sonra RichEditLog-a başlayın. Xətlər. Əlavə et ("[" + TimeToStr (Time ) + "] Müştəri əlaqəsi kəsildi: " + Socket. RemoteHost ); CheckListClient. Əşyalar. Sil (i) ; zəngin editlog. İcra et(WM_VSCROLL, SB_BOTTOM, 0); son; son; nəhayət //-//-//-///-//-// sonu ; son;

Siyahıda olan bütün müştəriləri nəzərdən keçiririk və heç birini tapmasaq, onu TCheckListBox komponentindən silirik, yəni müştəri proqramındakı əlaqəni kəsin düyməsini sıxıb.




Üst