Konfiguracja sprzętu i oprogramowania

Tworzenie aplikacji klient-serwer z wykorzystaniem Indy w Delphi.

Serge Dosyukov Mike Pham

W tym artykule wyjaśniono, jak utworzyć samodzielną usługę sieciową przy użyciu pakietu Indy i Delphi 7 oraz jak używać pakietu Indy do obsługi usług sieci Web opartych na protokole SOAP firmy Delphi 7. Aby uzyskać więcej informacji na temat tworzenia usług internetowych, zapoznaj się z doskonałym artykułem Nicka Hodgesa na stronie społeczności Borland: Shakespeare on the Net.

Wcześniej czy później może być konieczne utworzenie serwera, który będzie samodzielnym serwerem HTTP i obsługuje usługi sieci Web. Na przykład, możesz chcieć stworzyć serwer aplikacji SOAP dla aplikacji n-warstwowej zbudowanej w Delphi.

Wstęp

Pomoc online Delphi zapewnia doskonałe sekwencyjne instrukcje tworzenia usługi sieciowej, serwera MIDAS (model COM, DCOM), ale niewiele jest informacji na temat tworzenia samodzielnej, wielowarstwowej aplikacji MIDAS opartej na SOAP.

Wcześniej opublikowane przez Dave'a Nottage'a. Ten artykuł opisał pomysł, jak stworzyć usługę sieciową z obsługą SOAP w Delphi 6 i opublikować interfejsy SOAP modułu Datamodule, czyli ten artykuł nauczył Cię, jak tworzyć własne n-warstwowe systemy MIDAS.

Delphi 7 firmy Borland i nowy pakiet Indy mają wbudowaną obsługę tej funkcji.

Jednak pomimo wbudowanej obsługi nie ma udokumentowanego opisu tej funkcji.

Ostatnie wpisy na webcastie firmy Borland oraz wyszukiwanie w sieci przy użyciu serwera Google pozwoliły autorom wymyślić sposób na przekonwertowanie istniejącego kodu z Delphi 6 do Delphi 7. Ale wszystko ma swój czas.

Główny pomysł

Ten artykuł jest pierwszą częścią trzyczęściowej serii. Opisuje główne przepisy. Część druga i trzecia zostaną poświęcone niektórym problemom i sposobom ich rozwiązywania. Zacznijmy opisywać główną ideę.

  • być samodzielnym serwerem HTTP;
  • użyj Indy jako platformy;
  • wsparcie publikowania przez SOAP;
  • być w stanie publikować SOAP DataModules, co pozwala na stworzenie własnego n-warstwowego serwera SOAP/HTML.

Serwer HTTP i SOAP

Wiele osób zna Indy i używało wcześniej komponentów THTTPServer. Nie jest trudno umieścić ten komponent w formularzu wniosku, ale jak sprawić, by obsługiwał SOAP? W katalogu "C: Program FilesBorlandDelphi7SourceIndy" znajdziesz plik IdHTTPWebBrokerBridge.pas. To jest dokładnie to, czego potrzebujesz.

Ten plik nie jest częścią pliku wykonywalnego Indy, więc musisz dołączyć go do bieżącego projektu jako domyślny plik projektu. (Do skompilowania projektu potrzebny będzie również plik IdCompilerDefines.inc.) Te pliki należy skopiować do katalogu bieżącego projektu. W celu zwiększenia szybkości mogą być wymagane zmiany kodu, dlatego najlepiej przechowywać te pliki oddzielnie od dystrybucji Indy.

Poniżej opisano implementację zastępowania komponentów z THTTPServer, która została rozszerzona o obsługę pakietów SOAP o nazwie TIdHTTPWebBrokerBridge. Ta konstrukcja jest klasą, która dziedziczy po TCustomHTTPServer i obsługuje podstawowe wiązanie zapytań.

Ponieważ ta klasa nie jest dostępna z palety, będziesz musiał zdefiniować ją jako zwykły obiekt podczas wykonywania kodu.

Ten obiekt może być używany dokładnie w taki sam sposób, jak zwykły serwer THTTPServer, z wyjątkiem tych dodatkowych właściwości, które sprawiają, że działa on z SOAP.
Przyjrzyjmy się jednak najpierw przygotowaniu wymaganego kodu.

WebBroker i Indy

Ci, którzy wcześniej tworzyli usługi sieci Web, wiedzą, że jest to wykorzystywane do tego celu. WebBroker... Delphi 7, podobnie jak Delphi 6, wykorzystuje architekturę WebBroker do obsługi protokołu SOAP.

Dlatego musisz stworzyć moduł Moduł TWeb i umieść w nim następujące trzy komponenty: THTTPSoapDispatcher, THTTPSoapPascalInvoker i TWSDLHTMLPublish. Wszystkie są dostępne w zakładce WebServices Palety Komponentów. Po powiązaniu SOAPDispatcher z SOAPPascalInvoker formularz wniosku jest gotowy. Wynik końcowy powinien być podobny do pokazanego na poniższym rysunku:

(moduł uWebModule.pas)

Najlepiej pozostawić wszystko tak, jak jest, ponieważ nie ma potrzeby modyfikowania ani wykonywania żadnego niestandardowego kodu dla tego formularza.

WebModuł i Indy

Przejdźmy do innego fragmentu kodu wymaganego do zaimplementowania serwera HTTP.

Jak widać, TIdHTTPWebBrokerBridge ma metodę RegisterWebModuleClass, która umożliwia zarejestrowanie własnego modułu WebModule i udostępnienie go serwerowi.

Zatem po utworzeniu obiektu serwera fServer wystarczy wywołać klasę fServer.RegisterWebModuleClass (TwmSOAPIndy).

Notatka. W typowej implementacji TIdHTTPWebBrokerBridge obiekt TwmSOAPIndy zostanie utworzony za każdym razem, gdy nadejdzie żądanie. Oczywiście nie jest to konieczne. Dlatego klasę można zmodyfikować, aby zapewnić trwałe tworzenie tego obiektu tak długo, jak długo istnieje obiekt serwera. Aby uzyskać więcej informacji, warto zapoznać się z dokumentacją dotyczącą realizacji zajęć.

Czy serwer jest gotowy?

Protokół UDP jest całkiem dobry do przesyłania wiadomości tekstowych, to znaczy, że możesz organizować lokalne czaty i tym podobne. Postanowiłem podać przykład najprostszej pracy z UDP w Delphi.

Instrukcja krok po kroku:

Dałem Ci przykład, ale wybacz mi, nie zacząłem opisywać każdej linijki, ponieważ Nie widzę nic trudnego i każdy może to rozgryźć.

Właściwie, jeśli coś jest niejasne, możesz zadać mi pytanie. A oto aktualny kod:

używa
Windows, komunikaty, narzędzia SysUtils, warianty, klasy, grafika, kontrolki, formularze,
Okna dialogowe, StdCtrls, IdUDPServer, IdBaseComponent, IdComponent, IdUDPBase,
IdUDPClient, IdSocketHandle;

rodzaj
TForm1 = klasa (TForm)
IdUDPClient1: TIdUDPClient;
IdUDPServer1: TIdUDPServer;
Przycisk 1: Przycisk T;
Etykieta1: Etykieta T;
procedura FormCreate (Nadawca: TObject);
procedura FormClose (Sender: TObject; var Action: TCloseAction);
procedura Button1Click (Nadawca: TObject);
procedura IdUDPServer1UDPRead (AThread: TIdUDPListenerThread; AData: TBytes;
Oprawa: TIdSocketHandle);
prywatny
(Oświadczenia prywatne)
publiczny
(Oświadczenia publiczne)
kończyć się;

var
Form1: TForm1;

($R * .dfm)
[b] // Procedura wysyłania wiadomości
procedura TForm1.Button1Click (Sender: TObject);
zaczynać
próbować
IdUDPClient1.Aktywny: = Prawda;
IdUDPClient1.Host:= "host lokalny";
IdUDPClient1.Połącz;
jeśli IdUDPClient1.Połączony to
zaczynać
IdUDPClient1.Send (TimeToStr (czas));
Label1.Caption: = "ok";
kończyć się;
IdUDPClient1.Aktywny: = Fałsz;
Sygnał dźwiękowy Sygnał dźwiękowy Sygnał dźwiękowy
oprócz
MessageDlg („Coś poszło nie tak = (”, mtError,, 0);
kończyć się;
kończyć się;
[b]
//Włącz wyłączone. Serwer UDP podczas uruchamiania i zamykania formularza
procedura TForm1.FormClose (Sender: TObject; var Action: TCloseAction);
zaczynać
IdUDPServer1.Aktywny: = Fałsz;
kończyć się;

procedura TForm1.FormCreate (Sender: TObject);
zaczynać
IdUDPServer1.Aktywny: = Prawda;
kończyć się;

[b] // Procedura reakcji serwera podczas odbierania danych
procedura TForm1.IdUDPServer1UDPRead (AThread: TIdUDPListenerThread;
AData: TBy; Oprawa: TIdSocketHandle);
Var
i: liczba całkowita;
s: ciąg;
zaczynać
s: = "";
próbować
i: = 0;
while (AData [i] 0) do
zaczynać
s: = s + chr (AData [i]);
ja: = ja + 1;
kończyć się;
wreszcie
Etykieta1.Podpis: = s;
kończyć się;
kończyć się;

Oprócz podstawowych usług i protokołów internetowych istnieje szeroka gama usług dodatkowych, z których możliwości często korzystają twórcy Internetu. Ponadto możliwość wyświetlania informacji za pomocą przeglądarki nie zawsze jest akceptowalnym rozwiązaniem dla aplikacji internetowych. W takim przypadku zasadne jest wykorzystanie infrastruktury internetowej do wymiany danych oraz udostępnienie wyświetlania informacji poprzez bardziej złożone aplikacje klienckie tworzone np. w Delphi.

Załóżmy, że chcesz zaimplementować niestandardową logikę po stronie serwera, która nie jest wbudowana w standardowe serwery sieci Web. Aby rozwiązać tę klasę problemów, Delphi zawiera bibliotekę Internet Direct (Indy) firmy Nevrona Designs (http://www.nevrona.com/Indy/). Ta biblioteka, opracowana specjalnie dla Borland Delphi, ma osiem wersji, z których ostatnia została zawarta w Nowa wersja Delfów. Zestaw komponentów podzielony jest na trzy grupy: klient (Indy Client), serwer (Indy Servers) i pomocniczy (Indy Misc).

Klienci i serwery Indy

Większość komponentów Indy Client i Indy Servers to pary odpowiadające klientowi i serwerowi części protokołów i usług (z wyjątkiem oddzielnych, głównie serwerowych, komponentów takich jak TunnelMaster i TunnelSlave) i umożliwiają korzystanie z protokołów takich jak TCP / IP, UDP, NNTP, SMTP, FTP, HTTP oraz ECHO, FINGER, WHOIS itp. (rys. 1).

Komponenty klienta Indy są pisane przy użyciu gniazd. Gniazdo po stronie klienta wymaga połączenia z serwerem. Jeśli komunikacja zostanie nawiązana, klient i serwer mogą rozpocząć wymianę wiadomości. Wiadomości te mają różny charakter, ale zazwyczaj wymiana odbywa się według określonego protokołu (np. HTTP) (rys. 2).

TIdTCPClient i TIdTCPServer

Komponenty te służą do obsługi jednego z głównych protokołów sieciowych - ТСР (protokół kontroli transmisji), a także są klasami bazowymi dla komponentów TIdSMTP i TIdFTP. Klasa TIdTCPServer ma właściwość ThreadMgr, która domyślnie ma wartość zero. Jeśli ThreadMgr ma wartość zero, gdy wywoływany jest TIdTCPServer, klasa TIdThreadMgrDeafault zostanie utworzona niejawnie. V Inaczej używany jest zainstalowany menedżer procesów.

TIdUDPClient i TIdUDPServer

Komponenty te są używane do obsługi sieci UDP (User Datagram Protocol) i są również klasami bazowymi dla wielu innych komponentów Indy.

TIdDICTSerwer

Składnik serwera, który obsługuje protokół Dictionary Server Protocol (DICT), to oparty na protokole TCP słownik po stronie serwera, który umożliwia klientowi dostęp do słownika języka naturalnego.

TIDDISCARDSerwer

Komponent serwera obsługujący serwer nagrywający. Rekordy mogą służyć jako narzędzie do debugowania i pomiaru. Usługa nagrywania po prostu przekazuje wszelkie dane temu, kto zechce je otrzymać.

TI dEcho i TI dECHOServer

Komponenty są zaprojektowane tak, aby zapewnić responsywną usługę, zwykle używaną do sprawdzania kondycji sieci. Klient wysyła wiadomość tekstowa do serwera, serwer zwraca komunikat do klienta. Jeśli wiadomość jest nieczytelna, sieć działa nieprawidłowo.

TIdFinger i TIdFingerServer

Komponenty są zaprojektowane tak, aby zapewnić protokół, który umożliwia użytkownikowi zapytanie o dane dotyczące obecności innych użytkowników w systemie. Niektóre serwery obsługują takie żądania klientów. Korzystanie z tej pary komponentów umożliwi obsługę żądań klientów, które dowiadują się, czy w systemie są inni użytkownicy.

TIdFTP

Składnik zawiera pełne wsparcie protokół przesyłania plików - FTP (protokół przesyłania plików). Obsługuje pasywny i aktywny transfer danych, a także operacje takie jak GET i PUT, usuwanie katalogów, pobieranie kwot, rozmiarów plików i katalogów. TI dFTP wykorzystuje w swojej pracy klasę TIdSimpleServer. Gdy trwa przesyłanie pliku FTP, pomocnicze połączenie TCP jest otwierane do przesyłania danych i zamykane po przesłaniu danych. Takie połączenie nazywa się „kanałem danych”, który jest unikalny dla każdego przesyłanego pliku.

TIdGopher i TIdGopherServer

Te składniki mają na celu zapewnienie protokołu sieciowego, który został niedawno zastąpiony przez protokół HTTP z sieci WWW (World Wide Web). Serwer, który implementuje ten protokół, zapewnia hierarchiczny, rozproszony system obsługi przepływu pracy. Przykład użycia tej pary komponentów, znajdujących się w katalogach \demos\indy\GopherClient i \demos\indy\GopherServer, pokazuje, jak ten protokół może być wykorzystany do zapewnienia lokalna sieć informacje o plikach na Twoim komputerze, w tym zamkniętych.

TIdHostNameServer

Składnik serwera używany do przekazywania klientom nazwy serwera lokalnego.

TIdHTTP i TIdHTTPServer

Komponenty służą do zapewnienia protokół sieciowy HTTP (obsługiwane są wersje 1.0 i 1.1, w tym operacje GET, POST i HEAD). Zapewnia również obsługę uwierzytelniania i korzystania z serwerów proxy. Składnik serwera służy do świadczenia usług na inny serwer sieciowy, który obsługuje ten protokół. TIdHTTPServer ułatwia wdrażanie funkcji, takich jak pliki cookie, zarządzanie stanem i inne.

TIdIcmpKlient

Składnik klienta przeznaczony do udostępniania protokołu ICMP (Internet Control Message Protocol), za pomocą którego wykonywane są operacje ping i śledzenie sieci.

TIdPOP3

Komponent klienta zaprojektowany w celu zapewnienia protokołu POP (Post Office Protocol), w tym obsługi kodowania i dekodowania MIME oraz transmisji znaków wielobajtowych.

TIdIMAP4Serwer

Składnik serwera przeznaczony do obsługi operacji protokołu IMAP (Internet Message Access Protocol) na serwerze. Protokół umożliwia wyszukiwanie wiadomości E-mail na serwerze. Różnica między protokołami IMAP i POP polega na tym, że protokół POP wymaga dodatkowej pamięci do przechowywania danych, a protokół IMAP adresuje serwer, a nie komputer klienta. IMAP4 został stworzony w celu zastąpienia POP3, ale POP3 pozostaje powszechnie używanym standardem do dnia dzisiejszego.

TIdIRCSerwer

Komponent serwera przeznaczony do obsługi najczęściej używanych operacji serwisowych w Internecie, potocznie nazywany czatem. Komponent dostarcza podstawowych elementów konstrukcyjnych dla serwera IRC (Internet Relay Chat).

TIdMappedPortTCP

Komponent serwerowy do tworzenia mapowanych portów, które są często używane w serwerach proxy. Metody tego komponentu umożliwiają mapowanie jednego portu na drugi. Na przykład port 80 można zmapować na port 3000, a wszystkie żądania do pierwszego portu (port 80) będą przekazywane do drugiego portu (port 3000).

TIdNNTP i TIdNNTPServer

Te składniki są wymagane do obsługi protokołu NNTP (Network News Transfer Protocol) używanego w usługach informacyjnych. Komponent klienta obejmuje obsługę kodowania i dekodowania MIME, a także obsługę znaków wielobajtowych i kodowania alternatywnego. Komponent serwera umożliwia tworzenie serwerów grup dyskusyjnych. Należy zauważyć, że TIdNNTPServer nie jest w pełni funkcjonalnym serwerem grup dyskusyjnych, ale komponentem zapewniającym podstawową funkcjonalność takiego serwera grup dyskusyjnych.

TIdQOTD i TIdQOTDSerwer

Komponenty służą do świadczenia usługi Wycena Dnia. Komponent klienta łączy się z instancją komponentu serwera w celu pobrania dziennej wyceny. Każda instancja serwera zawiera unikalną bazę cytatów.

TIdSMTP

Składnik klienta przeznaczony do użytku w aplikacjach Simple Mail Transfer Protocol (SMTP), zapewniający obsługę uwierzytelniania, kodowania i dekodowania MIME oraz obsługę znaków wielobajtowych.

TIdSNTP

Składnik klienta zaprojektowany do świadczenia usługi czasu (Simple Network Time Protocol (SNTP). Może być używany do łączenia się z dowolną usługą czasu w celu określenia aktualnej daty i godziny.

TIdSimpleServer

Komponent serwerowy zapewniający lekki serwer TCP. Umożliwia zorganizowanie połączenia punkt-punkt. Służy do tworzenia serwerów z jednym użytkownikiem, co oznacza, że ​​jednocześnie może obsługiwać tylko jedno połączenie. W przeciwieństwie do składnika TIdTCPServer nie tworzy procesów pomocniczych podczas oczekiwania na żądania od klientów i podczas przetwarzania tych żądań. Innymi słowy, jeśli serwer obsługuje żądanie od jakiegoś klienta, a w tym czasie inny klient kontaktuje się z nim, aby się połączyć, zostanie on zablokowany do czasu zakończenia przetwarzania pierwszego żądania.

TIdTelnet i TIdTelnetServer

Składnik klienta służy do ustanawiania sesji zdalnych na innym komputerze, w tym negocjacji i uwierzytelniania konsoli. Protokół komunikacyjny zakłada obecność osoby, która interaktywnie wchodzi w interakcję z serwerem. Komponent klienta nie obsługuje wyświetlania i emulacji terminala, ale po prostu zapewnia połączenie z po stronie serwera... Zazwyczaj protokół serwera TIdTelnetServer służy do organizowania zdalne bazy dane z interfejsem tekstowym do interaktywnej interakcji z klientami.

TIdTime i TIdTimeServer

Komponent klienta jest alternatywą dla komponentu TIdSNTP do pomiaru czasu. Należy zauważyć, że formaty tych dwóch protokołów są różne. TIdTime jest oparty na formacie RFC 868 (zwraca czas w wewnętrznym standardzie UNIX OS, dokonując niezbędnych konwersji). Komponent serwera jest podobny w działaniu do serwera DayTime. Może służyć do implementacji usługi czasu na komputerze lokalnym. Nie jest wymagany dodatkowy kod, wystarczy utworzyć instancję TIdTimeServer, która zwróci czas wewnętrznego zegara komputera serwera.

TIdTrivialFTP i TIdTrivialFTPServer

Te komponenty są wymagane do zorganizowania najprostszego protokołu przesyłania plików. Komponent klienta tego protokołu jest używany do łączenia się z instancją odpowiedniego komponentu serwera. Protokół jest przeznaczony do prywatnych, lekkich, lokalnych przypadków przesyłania plików, na przykład w sieciach lokalnych lub do ładowania (rozładowywania) tablic routingu do routerów. Ze względu na osłabioną charakterystykę tego protokołu nie zaleca się jego stosowania w przypadku stosowania algorytmów uwierzytelniania lub jakichkolwiek innych mechanizmów bezpieczeństwa. Głównym celem tego protokołu jest przesyłanie plików na urządzenie sprzętowe w celu jego modyfikacji.

TIdTunnelMaster i TIdTunnelSlave

Komponenty tunelu po stronie serwera są używane w serwerach proxy do organizowania wielu połączeń logicznych w ramach jednego połączenia fizycznego (tunelowego). Klasy te mogą być używane do różnych celów, na przykład do organizowania tajnego połączenia przez niesklasyfikowane kanały.

TIDWhois i TIDWhoIsServer

Ten składnik klienta łączy się z dowolnym standardowym serwerem Whois, który udostępnia informacje o domenie. Komponent serwera zapewnia podstawową funkcjonalność serwera NIC.

Indy różne

Strona palety Indy Miscellaneous Components zawiera BASE64, UUE, Quoted Printable i inne popularne formaty komunikacji e-mail, kodery (MD2, MD4 i MD5) dla standardów kryptograficznych, używane do przechowywania haseł i podpisów elektronicznych w sposób nieodwracalny (trudny do odszyfrowania) formularz, a także wiele innych przydatnych komponentów i narzędzi, które są często wykorzystywane przy tworzeniu aplikacji internetowych (rys. 3).

TIdAntiFreeze

Ze względu na algorytmy blokowe w komponentach Indy często zdarza się, że aplikacja „zacina się” podczas działania połączenia. Aby wykluczyć użycie procesów wtórnych (wątków) podczas organizowania komunikacji, aby zapobiec zamrożeniu (zamrożeniu) aplikacji, wystarczy umieścić określony komponent w formularzu.

Komponent działa poprzez analizę żądań ze stosu protokołów TCP/IP i wysyłanie wiadomości do aplikacji w czasie opóźnienia, gdy połączenia zewnętrzne są blokowane, co stwarza iluzję działającego kodu. Ponieważ komponent wpływa na zablokowane połączenia tylko dla procesu głównego, użycie TidAntiFreeze w procesach wtórnych aplikacji nie jest wymagane. Pamiętaj, że składnik TIdAntiFreeze spowalnia połączenia, ponieważ główny proces jest sporadycznie przerywany w celu przetwarzania wiadomości. Z tego wynika, że ​​należy zadbać o to, aby tworzona aplikacja nie poświęcała zbyt dużo czasu na przetwarzanie komunikatów, w tym OnClick, OnPaint, OnResize itp. W pewnym stopniu można to kontrolować za pomocą właściwości klasy TIdAntiFreeze. Użycie tego komponentu jest opcjonalne, ale pozwala rozwiązać problem synchronizacji połączeń z interfejsem wizualnym aplikacji.

TIdDateTimeStamp

Klasa do wykonywania operacji matematycznych na dacie i czasie ze względu na fakt, że protokoły internetowe używają różnych formatów daty i czasu; ponadto klienci i serwery mogą znajdować się w różnych strefach czasowych.

TIdLogDebug

Celem tego komponentu jest przechwycenie zdarzeń dowolnego komponentu klienta lub serwera i zapisanie rekordu zdarzenia w określonym pliku. Komponent ten jest bardzo przydatny do debugowania komponentów Indy.

TIdMessage

Komponent jest używany w połączeniu z innymi komponentami do prawidłowego odszyfrowywania lub kodowania wiadomości. Mogą to być komponenty POP, SMTP i NNTP. Klasa obsługuje szyfrowanie i odszyfrowywanie MIME, znaki wielobajtowe i kodowanie ISO.

Kalkulator sieci TId

Jeden z niewielu komponentów Indy, których możesz używać podczas tworzenia aplikacji. Kalkulator sieci może służyć do obliczeń wykonywanych na adresach IP, w tym masek sieci, podsieci, klas sieci itp.

TIdThreadMgrDefault

Komponent domyślnie zapewnia zarządzanie procesami wtórnymi. Zgłaszany, gdy instancja klasy TIdThreadManager nie jest zdefiniowana dla żadnego komponentu Indy obsługującego zarządzanie procesami. Komponent zapewnia tylko podstawowe możliwości zarządzania procesami wtórnymi: tworzy je i niszczy na żądanie.

TIdThreadMgr Pool

Bardziej zaawansowany komponent zarządzania procesami niż TIdThreadMgrDefault, ponieważ łączy procesy zamiast tworzyć lub zabijać je na żądanie.

TIdVCard

VCard - elektroniczny odpowiednik wizytówki, może zawierać dane osobowe właściciela, dane graficzne.

TIdIMFDekoder

Przeznaczony do dekodowania wiadomości internetowych. Dziedziczy z klasy TIdCoder, podobnie jak wszystkie inne komponenty kodera. Klasa TIdCoder wykonuje dekodowanie zgodnie z internetowym formatem wiadomości tekstowych ARPA RFS-822, zaproponowanym w sierpniu 1982 r., oraz standardem wymiany wiadomości RFC 1036 USENET, zaproponowanym w grudniu 1987 r.

Komponent rozszerza możliwości klasy TIdCoder, umożliwiając wykrywanie formatu RFS-822 przez kontekst nagłówków, zapewniając tryb deszyfrowania po odebraniu oraz szyfrowanie i deszyfrowanie MIME. Składnik TIdIMFDecoder jest używany w klasie TIdMessageClient do dekodowania odebranych i przesłanych komunikatów.

TIdCytowany koder do druku

QuotedPrintableEncoder umożliwia odszyfrowanie tekstu w określonym formacie. Może służyć jako samodzielny komponent z określonym typem kodowania, który umożliwia wysyłanie wiadomości zawierających nowy typ kodowania.

Koder TIdBase64

Implementuje inny algorytm szyfrowania, który umożliwia przesyłanie znaków niedrukowalnych.

TIdUUEncoder

Implementuje jeden z pierwszych algorytmów szyfrowania, kodowanie UU. Czasami używane podczas publikowania artykułów w serwisie informacyjnym.

TIdXXEnkoder

Ta metoda szyfrowania prawie nigdy nie będzie używana. Zasadniczo jest to to samo kodowanie UU, ale z inną tabelą szyfrowania.

TIdCoderMD2

Komponenty z różnymi odmianami algorytmu szyfrowania MD (Message Digest). Wszystkie są oparte na tasowaniu, są jednokierunkowe i nie mają algorytmów deszyfrowania.

Komponenty klientów protokołu i serwerów mogą być używane do tworzenia aplikacji internetowych serwera i klienta, razem lub zamiast podstawowych (ClientSocket, ServerSocket) i innych komponentów z palety Internet i Fastnet. Komponenty Indy nie wykorzystują architektury WebBroker, implementując niskopoziomową obsługę protokołów i usług internetowych bezpośrednio w swoim kodzie źródłowym (w tym źródła).

TIdConnectionInterceptOpenSSL i TIdServerInterceptOpenSSL

Protokół Secure Sockets Layer (SSL), który zapewnia poufność i niezawodność komunikacji między dwiema aplikacjami, ma dwie warstwy. Na niskim poziomie warstwowego protokołu transportowego (takiego jak TCP) SSL jest protokołem rejestrującym i służy do enkapsulacji różnych protokołów wyższego poziomu. Zaletą SSL jest to, że jest to protokół niezależny od aplikacji, a protokół wyższej warstwy może być używany przez SSL.

SSL zapewnia bezpieczeństwo komunikacji, które ma trzy główne funkcje: zabezpieczenie poufnego połączenia; szyfrowanie kluczem publicznym (służy do potwierdzenia tożsamości adresata); wsparcie dla niezawodności transmisji danych.

  • Kryptografia symetryczna służy do szyfrowania danych (np. DES, RC4 itp.).
  • Podpis cyfrowy wyposażone w asymetryczne szyfrowanie kluczem publicznym (np. RSA, DSS itp.).
  • Niezawodność komunikacji, transport komunikatu obejmuje sprawdzanie integralności komunikatu za pomocą kodów korekcji MAC, bezpiecznych funkcji skrótu (np. SHA, MD5, itp.) z wykorzystaniem obliczeń MAC.

W połączeniu z uwierzytelnianiem HTTP i serwerem, SSL zapewnia wymaganą funkcjonalność szyfrowania i dodatkowo utrzymuje ustanowione połączenie poprzez ponowną weryfikację tożsamości serwera WWW itp. Ważne jest, aby zrozumieć, że SSL chroni tylko komunikację podczas przesyłania danych i nie zastępuje innych mechanizmów bezpieczeństwa.

Komponenty TIdConnectionInterceptOpenSSL i TIdServerInterceptOpenSSL zapewniają połączenie zarówno po stronie klienta, jak i serwera zgodnie z protokołem SSL. Należy zauważyć, że komponenty TIdConnectionInterceptOpenSSL i TIdServerInterceptOpenSSL są dostępne tylko w Delphi 6, ale nie w Kylix. Wynika to ze złożoności protokołu, który w przypadku implementacji Windows opiera się na funkcjonalności systemu operacyjnego.

Przykłady wykorzystania komponentów Indy można znaleźć w katalogach / Delphi6 / Demos / Indy. W sumie biblioteka Indy w wersji 8.0 zawiera 69 komponentów. Stwierdzono, że w wersji 9.0 podana biblioteka będzie zawierać 86 komponentów. Wszystkie komponenty są zunifikowane i zawarte zarówno w Delphi 6, jak i Kylix, co pozwala na ich wykorzystanie do tworzenia aplikacji wieloplatformowych. Wszystkie komponenty Indy obsługują wielowątkowość.

Komponenty Indy realizują prawie całą funkcjonalność dostępną w komponentach Internet i Fastnet, co wyraźnie widać w tabeli.

Wyjątkiem są klasy takie jak TNMMsgServ, TNMMsg, TNMStrm, TNMStrmServ, TpowerSock, TNMGeneralServer, TNMURL, które albo implementują przestarzałe protokoły, albo mają funkcjonalność zaimplementowaną w dużej grupie klas alternatywnych.

Jednak w przeciwieństwie do swoich poprzedników, komponentów Internet i Fastnet, Indy posiada bogatszą prezentację komponentów serwerowych oraz komponentów do transkodowania i szyfrowania danych, a także wsparcie dla uwierzytelniania (paleta Indy Misc). Jak widać z powyższej tabeli, podstawowe protokoły i usługi są dostarczane nie tylko przez klienta, ale także przez komponent serwera. Są to usługi czasu, odpowiedzi, uzyskania informacji o użytkowniku, a także Protokoły HTTP, NNTP, UDP, a nawet najprostszy FTP.

Kilka przykładów użycia komponentów Indy

W komponentach Delphi's Indy adres IP jest zdefiniowany we właściwości Host, zwykle tylko w aplikacjach klienckich. Składniki hostowane na serwerze mają metody, które umożliwiają rozpoczęcie lub zatrzymanie sondowania odpowiedniego portu — na przykład zmiana właściwości Active składnika IdTCPServer uruchamia lub zatrzymuje sondowanie odpowiedniego portu. Po nawiązaniu komunikacji między klientem a serwerem można rozpocząć przesyłanie danych.

Komponenty Indy kładą duży nacisk na bezpieczeństwo i niezawodność danych. Na przykład składnik IdTCPClient ma metody Connect i Disconnect. Zastosowanie techniki programowania jak w poniższym kodzie od strony klienta:

Z TCPClient rozpocznij Connect; spróbuj lstMain.Items.Add (ReadLn); wreszcie Odłącz; kończyć się; kończyć się;

oraz za pomocą właściwości Connection przekazanej jako parametr instancji AThread klasy TIdPeerThread od strony serwera:

Z AThread.Connection rozpocznij WriteLn ("Witaj z serwera Basic Indy Server."); Rozłączyć się; kończyć się;

możesz polegać na tym, że połączenie zostanie wykonane normalnie lub błąd zostanie prawidłowo obsłużony.

Zwróć uwagę na metody ReadLn i WriteLn odpowiednich klas - przypominają one standardowe instrukcje I/O Pascala. Jest to hołd dla technik programowania UNIX, w których większość operacji systemowych jest wykonywana poprzez odczytywanie i zapisywanie do odpowiednich plików.

Podobnie jak komponenty Fastnet, klasy komponentów Indy zawierają zdarzenia, których można użyć do organizowania kontroli zdarzeń. Na przykład możesz ustawić wyświetlanie wiadomości w formularzu podczas łączenia się z klientem:

Procedura TForm1.IdECHOServer1Connect (AThread: TIdPeerThread); begin lblStatus.caption: = "[Obsługa klienta]"; kończyć się;

Indy dostarcza komponenty, które implementują protokoły po stronie klienta i serwera, które są unikalne dla tej biblioteki. Komponenty TIdGopherServer i TIdGopher, dzięki metodom GetExtendedMenu, GetFile, GetMenu, GetTextFile na Strona klienta oraz ReturnGopherItem, SendDirectoryEntry - po stronie serwera pomoc w przeglądaniu plików różnych typów, w tym te oznaczone jako ukryte, a także katalogi włączone komputer zdalny(podobnie jak polecenie dir *. * w systemie operacyjnym MS-DOS).

Korzystając ze składników IdSMTP i IdMessage, możesz łatwo stworzyć własną aplikację internetową, która może wysyłać pocztę za pomocą protokołu SMTP (Rysunek 4).

W tym przypadku klasa IdMessage (jeden z 23 komponentów ze strony Indy Misc) odpowiada za wygenerowanie wiadomości, która wynika z jej nazwy, a IdSMTP odpowiada za zorganizowanie połączenia z serwerem pocztowym.

Technologia Indy wykorzystuje blokujące operacje odczytu i zapisu. Każda operacja Connect używana w Indy czeka na zakończenie połączenia. Podczas pracy z komponentami klienta Indy z reguły należy wykonać następujące operacje:

  • zażądać połączenia z serwerem;
  • wysyłać do serwera żądania odczytu i zapisu (w zależności od typu serwera krok wykonywany jest jednorazowo lub wielokrotnie);
  • zakończyć połączenie z serwerem i rozłączyć.

Komponenty Indy zostały zaprojektowane tak, aby zapewnić najwyższą jakość wysoki poziom abstrakcja. Zawiłości i szczegóły stosu TCP/IP są ukryte przed programistą, aby mógł skupić się na wykonywanych zadaniach.

Poniższy mały przykład pokazuje typową sesję komponentów klienta:

Z IndyClient rozpocznij Host: = "zip.pbe.com"; // Host do wywołania Port: = 6000; // Port do wywołania serwera na Connect; spróbuj // Twój kod w końcu trafia tutaj Odłącz; kończyć się; kończyć się;

W tym przykładzie, nawet jeśli połączenie z serwerem nie zostanie nawiązane, połączenie zostanie bezpiecznie zakończone przy użyciu instrukcji try-finally.

Komponenty serwera Indy opisują różne modele serwerów, których można używać w zależności od potrzeb i używanego protokołu.

TIdTCPServer jest najczęściej używanym składnikiem serwera, który tworzy dodatkowy proces, który jest niezależny od głównego procesu aplikacji. Stworzony proces czeka na przychodzące zapytania od potencjalnych klientów. Dla każdego klienta, na który odpowiada, tworzony jest indywidualny proces wtórny. Zdarzenia powstające w procesie obsługi są skorelowane z kontekstem odpowiednich procesów (rys. 5).

Innymi słowy, dla każdego połączenia klienta klasa TIdTCPServer używa unikatowego wątku dodatkowego, wywołując procedurę obsługi zdarzeń OnExecute wątku. Formalnym parametrem metody OnExecute jest odwołanie do instancji klasy Athread odpowiadającej utworzonemu wątkowi. Właściwość Connection tej klasy jest odwołaniem do klasy TIdTCPConnection, która jest tworzona w celu przetworzenia żądania klienta. TIdTCPConnection obsługuje odczytywanie i zapisywanie połączenia oraz nawiązywanie i kończenie sesji.

Protokół UDP działa bez uprzedniego nawiązania połączenia z serwerem (każdy wysłany pakiet jest niezależnym zestawem danych, a nie częścią dużej sesji lub połączenia). Podczas gdy TIdTCPServer tworzy oddzielne wątki dla każdego połączenia, TIdUDPServer używa wątku głównego lub pojedynczego wątku pomocniczego, który obsługuje wszystkie żądania UDP. Gdy TIdUDPServer jest aktywny, tworzony jest wątek do nasłuchiwania przychodzących pakietów UDP. Dla każdego odebranego pakietu zdarzenie OnUDPRead jest wywoływane w wątku głównym lub w kontekście wątku nasłuchującego, w zależności od wartości właściwości ThreadedEvent. Gdy ThreadedEvent ma wartość False, zdarzenie jest zgłaszane w wątku głównym, w przeciwnym razie w wątku nasłuchującym. Podczas przetwarzania zdarzenia inne operacje serwera są blokowane. Dlatego ważne jest, aby procedury OnUDPRead były wykonywane tak szybko, jak to możliwe.

Jeśli chcesz utworzyć nową aplikację kliencką dla istniejącego serwera przy użyciu istniejącego protokołu, Twoim zadaniem jest wyłącznie opracowanie i debugowanie aplikacji klienckiej. Jednakże, jeśli chodzi o tworzenie aplikacji klienckich i serwerowych przy użyciu istniejącego lub nowego protokołu, mamy do czynienia z klasycznym problemem kurczaka i jajka. Od czego zacząć programowanie - od klienta czy od serwera?

Oczywiście w końcu trzeba stworzyć zarówno klienta, jak i serwer. W przypadku wielu aplikacji, zwłaszcza korzystających z protokołu tekstowego (takiego jak HTTP), łatwiej jest rozpocząć budowę aplikacji od zaprojektowania serwera. Aby go debugować, istnieje wygodny klient, który już istnieje. Jest to aplikacja konsoli Telnet, która jest dostępna zarówno w systemie Windows, jak i UNIX.

Jeśli wpiszesz polecenie konsoli telnet 127.0.0.1 80 z adresem IP komputera lokalnego i portem 80 używanym domyślnie przez serwery WWW, wtedy aplikacja odpowie tekstem pokazanym na rys. 6 dla Windows 2000 i IIS 5.0.

Aby stworzyć najprostszy serwer przy użyciu komponentów Indy, potrzebujesz:

  1. Tworzyć nowy projekt.
  2. Umieść instancję komponentu TIdTCPServer z palety Indy Servers na głównym formularzu projektu (rys. 7).
  3. Ustaw właściwość DefaultPort instancji klasy TIdTCPServer1 na 6002 (zalecane jest ustawienie dużych wartości, aby uniknąć zduplikowanych numerów portów w różnych aplikacjach), a właściwość Active na True.
  4. Dodaj następujący tekst do metody instancji TIdTCPServer1 obsługującej zdarzenie OnExecute: procedure TForm1.IdTCPServer1Execute (AThread: TIdPeerThread); var s: ciąg; i: liczba całkowita; zacznij od AThread.Connection spróbuj WriteLn ("Wpisz liczbę całkowitą i Enter"); s: = CzytajLn; spróbuj i: = StrToInt (s); WriteLn (s + "kwadrat to" + IntToStr (i * i)); z wyjątkiem WriteLn (s + "nie jest liczbą całkowitą"); kończyć się; wreszcie Odłącz; kończyć się; kończyć się;

    Metody, takie jak powyższa procedura obsługi zdarzeń, muszą zawierać instrukcje try-finally, aby móc zakończyć połączenie z klientem, niezależnie od tego, jak zostały przetworzone instrukcje wykonane na połączeniu, i aby poprawnie obsługiwać nieoczekiwane opóźnienia połączeń.

  5. Skompiluj i zapisz projekt, uruchom go jako samodzielny program lub z poziomu Delphi, po wybraniu z menu głównego polecenia IDE Tools | Opcje debugera i wyłączenie opcji debugowania zintegrowanego znajdującej się w lewym dolnym rogu okna (Rysunek 8).
  6. Otwórz okno konsoli i wpisz telnet 127.0.0.1 6002.
  7. W oknie wyświetli się tekst, który tworzy serwer (rys. 9).
  8. Wpisując np. cyfrę 9, można zobaczyć reakcję serwera w postaci pokazanej na rys. 10 .

    W rzeczywistości, aby zapewnić synchronizację, po naciśnięciu klawisza Enter w kontekście klienta na serwerze na serwerze pojawia się tzw. inni potencjalni klienci. Jednocześnie, ponieważ każde żądanie od klienta jest przetwarzane niezależnie i jednocześnie, usługa po stronie serwera występuje średnio w tym samym czasie. Gdybyś miał programować serwer bez użycia komponentów Indy, musiałbyś sam wspierać tego typu operacje.

  9. Za pomocą polecenia wyjścia w systemie Windows i „ctrl +]” w systemie UNIX można wyjść z okna konsoli.
  10. Jeśli podczas wykonywania kroku 5 opcja uruchamiania została użyta od dołu środowisko programistyczne, zresetuj opcję debugowania zintegrowanego.

Jeśli potrzebujesz zaprojektować serwer, który nie tylko poprawnie poinformuje swoich klientów o zerwaniu połączenia, ale również przekaże im informacje o błędach, które wystąpiły, użyj instrukcji try-except zamiast try-finally, np. jak pokazano w poniższym przykładzie:

Procedura TDataModule1.IdTCPServer1Execute (AThread: IdPeerThread); var s: ciąg; zacznij od AThread.Connection spróbuj spróbować s: = ReadLn; // Wykonaj tutaj zadanie serwera // jeśli nie zgłoszono żadnego wyjątku, // zapisz odpowiedź serwera WriteLn (s); z wyjątkiem e: Exception do begin WriteLn (e.Message); end; // on end;// spróbuj z wyjątkiem ostatecznie Disconnect;end;end;

Ten mały przykład ilustruje kroki związane z tworzeniem prostego serwera tekstowego i sposobem jego debugowania.

Powyższy serwer jest typowym przykładem organizacji nowoczesnego przetwarzania rozproszonego.

Funkcje tworzenia aplikacji wielowarstwowych

Ostatnio do realizacji żądań klientów coraz częściej używa się wielu serwerów. Serwer tego typu po otrzymaniu żądania klienta i częściowym przygotowaniu go do dalszego przetwarzania kontaktuje się z innym serwerem i przesyła mu przekształcone żądanie lub żądania. Serwer drugiego poziomu może z kolei komunikować się z innymi serwerami. Możemy więc mówić o wielowarstwowej architekturze serwera.

Następnie stworzymy serwer dostępu do danych, którego zadaniem jest zwracanie danych z bazy danych. Serwer ten jednak nie odczytuje i nie zapisuje bezpośrednio do plików bazy danych. Zamiast tego kontaktuje się z serwerem bazy danych w poszukiwaniu danych żądanych przez klienta.

Rozpoczynamy więc tworzenie aplikacji o architekturze trójwarstwowej. Aby stworzyć serwer bazy danych przy użyciu komponentów Indy, musisz:

  1. Utwórz nowy projekt.
  2. Umieść instancję komponentu TIdTCPServer z palety Indy Servers w głównym formularzu projektu.
  3. Ustaw właściwość DefaultPort instancji klasy TIdTCPServer1 na 6001 (zalecane jest ustawienie dużych wartości, aby uniknąć zduplikowanych numerów portów dla różnych aplikacji), a właściwość Active na true.
  4. Dodaj do projektu nowy moduł wybierając polecenie Plik | Nowy | Data Module i umieść na nim instancje komponentów SQLConnection i SQLDataSet z zakładki dbExpress na palecie komponentów.
  5. Ustaw właściwość ConnectionName klasy SQLConnection na IBLocal i LoginPrompt na False. Jeśli nie skonfigurowałeś IBLocal w bazie danych worker.gdb, wykonaj najpierw tę procedurę.

Indy to dość potężny pakiet komponentów, który pozwala na tworzenie różnych aplikacji sieciowych. W tym samouczku pokażę, jak tworzyć aplikacje klient-serwer przy użyciu komponentów TIdTCPClient i TIdTCPServer.

Przede wszystkim chciałbym zwrócić uwagę na dwie ważne zalety tych komponentów. Najważniejszym z nich jest wielowątkowość, co oznacza, że ​​serwer tworzy osobny wątek dla każdego klienta, a to z pewnością wpływa na wydajność programu serwera na komputerach z procesorem wielordzeniowym. Drugą korzyścią jest łatwość użytkowania. Napisanie najprostszej aplikacji klient-serwer zajmuje 10-20 linijek kodu. Ten pakiet komponentów jest obecny w standardowych zespołach Delphi.

Napiszmy prosty program do wysyłania wiadomości tekstowej od klienta na serwer. Zacznijmy tworzyć serwer.
Umieść komponent IdTCPServer z zakładki "Indy Servers" w formularzu. Wszystkie ustawienia tego komponentu przeprowadzimy w czasie wykonywania w zdarzeniu OnCreate formularza:
IdTCPServer1.DefaultPort: = 12345;
IdTCPServer1.Aktywny: = prawda;
Tutaj wszystko jest proste – wskazujemy port, na którym będzie pracował serwer, a sam serwer aktywujemy.

W celu odebrania danych na serwerze od klienta odbywa się specjalne zdarzenie „OnExecute”. To wydarzenie wygląda tak:

zaczynać
kończyć się;

Zmodyfikujmy treść wydarzenia w następujący sposób:
procedura TForm3.IdTCPServer1Execute (AContext: TIdContext);
var
l: ciąg; // zmienna łańcuchowa, do której otrzymamy
zaczynać
l: = AContext.Connection.IOHandler.ReadLn();
Notatka1.Linie.Dodaj (l);
kończyć się;

Teraz, gdy tylko wiadomość dotrze do serwera, zapiszemy ją do zmiennej łańcuchowej l i wyślemy do wielowierszowego pola tekstowego.

Na tym o dziwo kończy się tworzenie serwera. Resztę zrobi za nas Indy. Zacznijmy od programu klienta. Połączy się z serwerem, wyśle ​​do niego wiadomość i rozłączy się z serwerem.

Stwórzmy nowy projekt, umieśćmy komponent IdTCPClient na formularzu, który znajdziesz w zakładce "Indy Clients". Umieścimy również prostą Edytuj i przycisk. Stwórzmy dla przycisku obsługę zdarzeń OnClick, wewnątrz której piszemy:
IdTCPClient1.Port: = 12345;
IdTCPClient1.Host:= '127.0.0.1';
IdTCPClient1.Połącz;
IdTCPClient1.IOHandler.WriteLn (Edit1.Text);
IdTCPClient1.Rozłącz;

Tego kodu nie trzeba umieszczać w zdarzeniu OnCreate. Możesz umieścić ten kod w dowolnym miejscu.
W pierwszym wierszu przypisujemy port i musimy podać ten sam port, który wskazaliśmy w programie serwera, w przeciwnym razie klient po prostu nie znajdzie serwera. Następnie wskazujemy adres IP serwera. Sam serwer może być zlokalizowany zarówno w sieci lokalnej, jak i zdalnie. W tym drugim przypadku połączenie zostanie nawiązane przez Internet i konieczne będzie podanie adresu IP w Internecie.

Podałem adres „127.0.0.1”, co oznacza, że ​​serwerem jest komputer, na którym działa klient. Ta metoda jest bardzo wygodna do testowania aplikacji sieciowych.
Następnie łączymy się, wysyłamy wiadomość i rozłączamy.Tak jak sama wiadomość, możesz pobrać adres IP z Edit lub z dowolnej zmiennej typu string.

Zakończono również prace nad programem klienckim. Jak widać, Indy wykonuje dla nas kawał dobrej roboty, dzięki czemu nawet niedoświadczony programista może stworzyć własną aplikację sieciową.

Wprowadzenie do Indii

Wprowadzenie do Indii
Autor: Chad Z. Hower
Strona główna: http://www.atozedsoftware.com
Tłumaczenie: Anatolij Podgoretski
wprowadzanie
Napisałem ten artykuł, gdy aktualna wersja to Indy 8.0. Wiele z tego artykułu ma zastosowanie i jest bardzo przydatne w przyszłych wersjach Indy. Jeśli podobał Ci się ten artykuł i chciałbyś przeczytać bardziej szczegółowe artykuły, zajrzyj do książki Indy in Depth.
Indy blokuje
Indy używa gniazd blokujących. Tryb blokowania jest podobny do odczytu / zapisu pliku. Podczas odczytu danych lub zapisu funkcja nie powraca do końca operacji. Różnica w stosunku do pracy z plikami polega na tym, że połączenie może potrwać dłużej, ponieważ żądane dane nie są jeszcze dostępne, zależy to od szybkości działania sieci lub modemu.
Na przykład wywołanie metody jest po prostu wykonywane i czeka, aż kontrola zostanie zwrócona do punktu wywołania. Jeśli wywołanie się powiodło, z metody zostanie zwrócona kontrola, w przypadku błędu zostanie wyrzucony wyjątek.
Tryb blokowania nie jest krytyczny
Ze względu na tryb blokowania zostaliśmy wielokrotnie pokonani przez naszych przeciwników, ale tryb blokowania to nie diabeł.
Problem pojawił się po przeniesieniu Winsock na Windows. W Uniksie problem był zazwyczaj rozwiązywany przez bifurkację (wygląda to na wiele wątków, ale kosztem oddzielnych procesów zamiast wątków). Klienci i demony uniksowe musiały rozgałęziać procesy, aby uruchomić i używać trybu blokowania. Windows 3.x nie mógł być zrównoleglony i nie wspierał zbyt wielu wątków. Korzystanie z interfejsu blokującego może zawiesić interfejs użytkownika i sprawić, że programy przestaną odpowiadać. Dlatego do WinSock dodano tryby nieblokujące, dzięki czemu Windows 3.x, z jego ograniczeniami, może korzystać z WinSock bez blokowania głównego i jedynego wątku programu. Wymagało to innego programowania, Microsoftu i innych oczernianych trybów blokowania z pasją do ukrycia Wady systemu Windows 3.x.
Potem przyszedł Win32, który był w stanie obsługiwać wiele wątków. Ale w tym momencie mózgi były już sproszkowane (czyli twórcy uważali, że blokowanie gniazd to wytwór diabła) i trudno było zmienić to, co zrobili. Dlatego trwa oczernianie reżimów blokujących.
W rzeczywistości Unix ma tylko blokujące gniazda. Gniazda blokujące mają również swoje zalety i są znacznie lepsze dla wielu wątków, bezpieczeństwa i innych aspektów. Kilka rozszerzeń zostało dodanych do Uniksa dla nieblokujących gniazd. Działają jednak zupełnie inaczej niż w systemie Windows. Są też niestandardowe i niezbyt powszechne. Gniazda blokujące Unix są używane prawie we wszystkich przypadkach i będą nadal używane.
Zalety trybu blokowania · Łatwiejsze programowanie - Tryby blokowania są łatwiejsze do zaprogramowania. Cały niestandardowy kod może znajdować się w jednym miejscu i działać w naturalnej, sekwencyjnej kolejności. · Łatwiejsze przenoszenie na Unix - Ponieważ Unix używa gniazd blokujących, w tym przypadku łatwiej jest napisać przenośny kod. Indy wykorzystuje ten fakt do pisania spójnego kodu. · Lepiej pracować ze strumieniami — ponieważ gniazda blokujące są dziedziczone, są bardzo łatwe w użyciu w strumieniach.
Wady trybu blokowania · Interfejs użytkownika zawiesza się na klientach — Wywołanie gniazda blokującego nie powraca, dopóki nie zakończy ono swojego zadania. Gdy takie wywołanie jest wykonywane w głównym wątku aplikacji, aplikacja nie może przetwarzać komunikatów użytkownika. Powoduje to zawieszenie interfejsu użytkownika, nie aktualizuje okien, a inne komunikaty nie mogą być przetwarzane, dopóki sterowanie nie zostanie zwrócone z gniazda blokującego.
Składnik zapobiegający zamarzaniu TId
Indy ma specjalny komponent, który rozwiązuje problem z zawieszaniem się interfejsu użytkownika. Wystarczy dodać jeden składnik TIdAntiFreeze w dowolnym miejscu w aplikacji, aby móc wykonywać połączenia blokujące bez zamrażania interfejsu użytkownika.
TIdAntiFreeze działa na wewnętrznym liczniku czasu poza stosem i wywołuje Application.ProcessMessages po wygaśnięciu limitu czasu. Połączenia zewnętrzne do Indy nadal są blokowane i dlatego działają w ten sam sposób bez użycia składnika TIdAntiFreeze. Korzystanie z TIdAntiFreeze pozwala uzyskać wszystkie zalety blokowania gniazd, bez wad.
Gwintowanie
Strumienie kodu są prawie zawsze używane z gniazdami blokującymi. Gniazda nieblokujące mogą również korzystać ze strumieni, ale wymaga to dodatkowego przetwarzania, a ich zalety w tym przypadku są tracone w porównaniu do gniazd blokujących.
Korzyści ze strumieni · Priorytetyzacja — można skonfigurować priorytety poszczególnych strumieni. Pozwala to na przydzielenie mniej lub więcej czasu procesora do poszczególnych zadań. · Enkapsulacja – Każde połączenie może zawierać pozory interfejsu z innym połączeniem. · Bezpieczeństwo — każdy wątek może mieć różne atrybuty bezpieczeństwa. · Wiele procesorów — zapewnia przewagę w systemach z wieloma procesorami. · Nie wymaga serializacji — zapewnia pełną współbieżność. Bez wielu wątków wszystkie żądania powinny być przetwarzane w jednym wątku. Dlatego każde zadanie musi być podzielone na małe porcje, aby mogło działać szybko. Podczas gdy jeden blok jest wykonywany, wszystkie inne muszą czekać na jego zakończenie. Na końcu jednego bloku wykonywany jest następny i tak dalej. Dzięki wielowątkowości każde zadanie można zaprogramować jako pojedynczą jednostkę, a system operacyjny rozdziela czas między wszystkie zadania.
Strumienie ankiet
Tworzenie i niszczenie wątków wymaga bardzo dużych zasobów. Jest to szczególnie trudne w przypadku serwerów z krótkotrwałymi połączeniami. Każdy serwer tworzy strumień, używa go przez krótki czas, a następnie niszczy. Prowadzi to do bardzo częstego tworzenia i usuwania wątków. Przykładem tego jest serwer WWW. Wysyłane jest pojedyncze żądanie i zwracana jest prosta odpowiedź. Podczas korzystania z przeglądarki podczas przeglądania dowolnej witryny internetowej mogą wystąpić setki połączeń i rozłączeń
Wątki odpytywania mogą naprawić tę sytuację. Zamiast tworzyć i niszczyć wątki na żądanie, wątki są wybierane z listy nieużywanych, ale już utworzonych wątków z puli. Gdy wątek nie jest już potrzebny, jest zwracany do puli zamiast zostać zniszczony. Wątki w puli są oznaczone jako nieużywane i dlatego nie zużywają czasu procesora. Dla jeszcze większej poprawy, strumienie można dynamicznie dostosowywać do aktualnych potrzeb systemu.
Indy obsługuje wątki odpytywania. Pula wątków Indy jest dostępna za pośrednictwem składnika TIdThreadMgrPool.
Wiele wątków
Mocno obciążony serwer może wymagać setek, a nawet tysięcy wątków. Istnieje powszechne przekonanie, że setki i tysiące wątków mogą zabić twój system. To jest fałszywe przekonanie.
Na większości serwerów wątki czekają na dane. Podczas oczekiwania na połączenie blokujące wątek jest nieaktywny. Na serwerze z 500 wątkami tylko 50 może być jednocześnie aktywnych.
Liczba wątków działających w Twoim systemie może Cię zaskoczyć. Przy minimalnej liczbie uruchomionych serwerów i określonym uruchomione aplikacje mój system ma utworzone 333 wątki, nawet przy 333 wątkach procesor jest obciążony tylko w 1%. Mocno obciążony Serwer IIS(Microsoft Internet Information Server) może tworzyć setki i tysiące strumieni.
Strumienie i sekcje globalne
W przypadku wielu strumieni musisz zapewnić integralność danych podczas uzyskiwania do nich dostępu. Może to być trudne dla programistów bez wątków. Jednak z reguły większość serwerów nie musi korzystać z danych globalnych. Większość serwerów pełni izolowane funkcje. Każdy wątek wykonuje swoje własne izolowane zadanie. Globalne sekcje odczytu/zapisu są cechą wielu aplikacji wielowątkowych, ale nie są typowe dla serwerów.
Metodologia indy
Indy różni się od innych komponentów Winsock, do których jesteś przyzwyczajony. Jeśli pracowałeś z innymi komponentami, najlepszym rozwiązaniem jest zapomnieć o ich działaniu. Wiele innych komponentów używa wywołań nieblokujących (asynchronicznych) i działa asynchronicznie. Muszą reagować na zdarzenia, tworzyć automat stanów i często czekać na pętle.
Na przykład w przypadku innych komponentów podczas wywoływania połączenia należy albo poczekać na wystąpienie zdarzenia połączenia, albo w pętli czekać, aż właściwość wskaże, że połączenie wystąpiło. Dzięki Indy możesz wywołać metodę Connect i poczekać na jej powrót. Zwroty kosztów zostaną wykonane, jeśli połączenie się powiedzie lub zostanie zgłoszony wyjątek, jeśli wystąpi problem. Dlatego praca z Indy jest bardzo podobna do pracy z plikami. Indy pozwala umieścić cały kod w jednym miejscu, zamiast rozmazywać go na różnych wydarzeniach. Ponadto Indy jest bardzo prosty i najbardziej opływowy.
Czym różni się Indy
Przegląd · Wykorzystywane są połączenia blokujące · Niezorientowane na zdarzenia - zdarzają się zdarzenia, ale są one wykorzystywane do celów informacyjnych i nie są tak naprawdę wymagane. · Zaprojektowany dla wątków - Indy jest przeznaczony do wątków, jednak można go używać bez wątków. Programowanie sekwencyjne
Szczegółowe rozpatrzenie
Indy nie tylko używa połączeń blokujących (synchronicznych), ale również działa w ten sposób. Typowa sesja Indy wygląda tak:
z IndyClient zacznij
Połączyć; Próbować
// Zrób tutaj swoje rzeczy
wreszcie Odłącz; kończyć się;
kończyć się;
Z innymi komponentami wygląda to tak:
procedura TFormMain.TestOnClick (Nadawca: TComponent);
zaczynać
z SocketComponentem zacznij
Połączyć; próbować
gdy nie są połączone, zaczynają się
jeśli IsError to zacznij
Anulować;
kończyć się;

OutData: = "Dane do wysłania";
while length (OutData)> 0 do początku
Application.ProcessWiadomości;
kończyć się;
wreszcie Odłącz; kończyć się;
kończyć się;
kończyć się;
procedura TFormMain.OnConnectError;
zaczynać
IsError: = Prawda;
kończyć się;
procedura TFormMain.OnRead;
var
i: liczba całkowita;
zaczynać
i: = SocketComponent.Send (OutData);
OutData: = Kopiuj (OutData, i + 1, MaxInt);
kończyć się;
Wiele komponentów nie radzi sobie zbyt dobrze z izolowaniem programisty od stosu. Wiele elementów, zamiast izolować użytkownika od zawiłości stosu, po prostu zostawia go przy sobie lub zapewnia owinięcie stosu.
Szczególny sposób Indy
Indy został zaprojektowany od podstaw z myślą o wielowątkowości. Budowanie serwerów i klientów w Indy jest podobne do budowania serwerów i klientów w systemie Unix. Aplikacje uniksowe zwykle wywołują stos bezpośrednio z niewielką warstwą abstrakcji lub bez niej.
Zazwyczaj serwery Unix mają jeden lub więcej detektorów, które nasłuchują przychodzących żądań klientów. Dla każdego klienta, którego należy obsłużyć, tworzony jest nowy proces. To robi proste programowanie, każdy proces dotyczy tylko jednego klienta. Każdy proces rozpoczyna się we własnym kontekście bezpieczeństwa, który jest definiowany przez odbiornik lub proces oparty na istniejących prawach, tożsamości lub innych rzeczach.
Serwery Indy działają w bardzo podobny sposób. Windows, w przeciwieństwie do Unix, nie może dobrze replikować procesów, ale działa dobrze z wątkami. Serwery Indy tworzą osobny wątek dla każdego połączenia klienta.
Serwery Indy wyznaczają wątek nasłuchujący, który jest oddzielony od głównego wątku kodu programu. Wątek nasłuchujący nasłuchuje żądań przychodzących od klientów. Dla każdego klienta, który odpowiada, tworzony jest nowy wątek do obsługi klienta. Odpowiednie wydarzenia są następnie podawane w kontekście ten strumień.
Recenzja klienta Indy
Indy ma na celu zapewnienie bardzo wysokiego poziomu abstrakcji. Zamieszanie i ziarnistość stosu TCP/IP jest ukryte przed programistą.Zwykle typowa sesja klienta w Indy wygląda tak:
z IndyClient zacznij
Host: = "zip.pbe.com"; // Host do połączenia
Port: = 6000; // Port do połączenia z serwerem
Połączyć; Próbować
// Zrób tutaj swoje rzeczy
wreszcie Odłącz; kończyć się;
kończyć się;
Przegląd serwerów Indy
Komponenty serwera Indy tworzą wątek nasłuchujący, który jest odizolowany od głównego wątku kodu programu. Wątek nasłuchujący nasłuchuje żądań przychodzących od klientów. Dla każdego klienta, który odpowiada, tworzony jest nowy wątek do obsługi klienta. Odpowiednie zdarzenia są następnie podawane w kontekście tego wątku.

Praktyczne przykłady
Poniższe przykłady powinny pomóc w rozpoczęciu pracy z komponentami dla proste użycie, ale w celu zademonstrowania przykłady są wykonywane jako proste aplikacje... Niektóre projekty mają na celu zademonstrowanie różnych sytuacji. Te przykłady są również dostępne do pobrania jako pliki zip.
Uwaga od tłumacza: link na stronie nie działa.
Przykład 1 - Sprawdzanie kodu pocztowego
Pierwszy projekt został maksymalnie uproszczony. Wyszukiwanie według kodu pocztowego, klient pyta serwer, do którego miasta i województwa należy podany kod pocztowy.
Dla tych, którzy mieszkają poza Stanami Zjednoczonymi i nie wiedzą, co to jest kod pocztowy, jest to kod pocztowy wskazujący miejsce dostawy. Kody pocztowe mają długość 5 cyfr.
Protokół
Pierwszym krokiem w budowie serwera i klienta jest opracowanie protokołu. W przypadku protokołów standardowych jest to określone w odpowiedniej specyfikacji RFC. W przypadku kodu pocztowego protokół jest zdefiniowany poniżej.
Większość protokołów wymiany działa w trybie tekstowym. Wymiana oznacza, że ​​polecenie jest przesyłane, aw odpowiedzi stan i ewentualnie dane. Protokoły nie ograniczają się do wymiany, ale nadal używany jest zwykły tekst. Protokół określania kodu pocztowego ma również charakter tekstowy. Zwykły tekst ułatwia debugowanie protokołów i umożliwia komunikację między różnymi językami programowania i systemami operacyjnymi.
Po połączeniu serwer wysyła wiadomość powitalną, a następnie odbiera polecenie. To polecenie może mieć postać „Kod pocztowy x” (gdzie x to kod pocztowy) lub „Zakończ”. W odpowiedzi na polecenie ZipCode odpowiedź jest wysyłana jako jeden wiersz z odpowiedzią lub pusty wiersz, jeśli kod nie zostanie znaleziony. Polecenie Quit powoduje rozłączenie serwera. Serwer może zaakceptować wiele poleceń przed wysłaniem polecenia Zakończ.
Kod źródłowy serwera

jednostka ServerMain;

berło

używa

rodzaj

TformMain = klasa (TForm)

IdTCPServer1: TIdTCPServer;

procedura FormCreate (Nadawca: TObject);

procedura FormDestroy (Nadawca: TObject);

procedura IdTCPServer1Connect (AThread: TIdPeerThread);

prywatny

ListaKodówPocztowych: Ciągi TStrings;

publiczny

kończyć się;

FormMain: TformMain;

realizacja

(R * .DFM)

procedura TformMain.IdTCPServer1Connect (AThread: TIdPeerThread);

zaczynać

AThread.Connection .WriteLn ("Serwer kodów pocztowych Indy gotowy.");

kończyć się;

SCommand: ciąg;

zaczynać

Polecenie SC: = CzytajLn;

kończyć się;

kończyć się;

kończyć się;

procedura TformMain.FormCreate (Sender: TObject);

zaczynać

ListaKodówPocztowych: = TStringList.Create;

ZipCodeList.LoadFromFile (ExtractFilePath (Application.EXEName) + "ZipCodes.dat");

kończyć się;

procedura TformMain.FormDestroy (Sender: TObject);

zaczynać

ListaKodówPocztowych.Free;

kończyć się;

kończyć się.

Jedynymi częściami specyficznymi dla Indy w projekcie są składnik IdTCPServer1, metody IdTCPServer1Connect i IdTCPServer1Execute.
Formularz zawiera składnik IdTCPServer1 typu TIdTCPServer. Zmieniono następujące właściwości: · Active = True — po uruchomieniu aplikacji serwer nasłuchuje. · DefaultPort = 6000 — wartość portu dla tego projektu. Serwer nasłuchuje żądań klientów na tym porcie.
Metoda IdTCPServer1Execute jest skojarzona ze zdarzeniem OnExecute serwera. Zdarzenie OnExecute jest wywoływane po zaakceptowaniu połączenia klienta. Zdarzenie OnExecute różni się od innych znanych Ci zdarzeń. OnExecute jest wykonywany w kontekście wątku. Zdarzenie wątku jest wywoływane i argument AThread przekazany do metody jest do niej przekazywany. Jest to ważne, ponieważ wiele zdarzeń OnExecute może działać jednocześnie. Dzieje się tak, aby serwer mógł działać bez tworzenia nowego komponentu. Istnieją również metody, które można przesłonić podczas konstruowania potomków.
Zdarzenie OnConnect jest wywoływane po zaakceptowaniu połączenia i utworzeniu dla niego wątku. V ten serwer służy do wysłania wiadomości powitalnej do klienta. Opcjonalnie można to również zrobić w zdarzeniu OnExecute.
Zdarzenie OnExecute można zgłaszać wiele razy, dopóki połączenie nie zostanie rozłączone lub utracone. Eliminuje to konieczność sprawdzania połączenia pod kątem rozłączenia lub utraty pętli w ramach zdarzenia.
IdTCPServer1Execute używa dwóch podstawowe funkcje, CzytajLn i ZapisLn. ReadLn odczytuje ciąg z połączenia, a WriteLn wysyła ciąg do połączenia.
sPolecenie: = CzytajLn;
Powyższy kod pobiera ciąg znaków od klienta i umieszcza go w lokalnej zmiennej ciągu sCommand.

jeśli SameText (sCommand, "QUIT") to zacznij

zakończ w przeciwnym razie, jeśli SameText (Kopiuj (sCommand, 1, 8), "Kod pocztowy"), a następnie zacznij

WriteLn (ZipCodeList.Values ​​[Kopiuj (sCommand, 9, MaxInt)]);

kończyć się;


Następnie sCommand jest sprawdzany pod kątem poprawnych poleceń.
Jeśli polecenie to „Wyjdź”, wykonywane jest polecenie Rozłącz. Po rozłączeniu nie jest dozwolony odczyt ani zapis. Po zakończeniu zdarzenia wątek nasłuchujący nie wywołuje go już, ale czyści wątek i kończy połączenie.
Jeśli polecenie to „KodZip”, to parametr po poleceniu jest pobierany, a tabela jest skanowana pod kątem obecności miasta i stanu. Miasto i stan są następnie przekazywane do klienta lub pusty ciąg jest przekazywany, jeśli nie ma dopasowania.
Następnie metoda kończy działanie. Serwer ponownie podniesie zdarzenie, gdy tylko nadejdzie nowe polecenie, umożliwiając klientowi wysłanie wielu poleceń.
Kod źródłowy klienta

jednostka KlientGłówny;

berło

używa

Windows, komunikaty, narzędzia SysUtils, klasy, grafika, kontrolki, formularze, okna dialogowe,

StdCtrls, ExtCtrls, IdAntiFreezeBase,

IdAntiFreeze, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient;

rodzaj

TformMain = klasa (TForm)

Klient: TIdTCPClient;

IdAntiFreeze1: TidAntiFreeze;

Panel1: TPanel;

Panel2: TPanel;

MemoWejście: TMemo;

LboxWyniki: TListBox;

Panel3: TPanel;

Przycisk 1: Przycisk T;

Przycisk2: Przycisk T;

Etykieta1: Etykieta T;

procedura Button2Click (Nadawca: TObject);

procedura Button1Click (Nadawca: TObject);

prywatny

publiczny

kończyć się;

FormMain: TformMain;

realizacja

(R * .DFM)

procedura TformMain.Button2Click (Sender: TObject);

zaczynać

Notatka.Wyczyść;

LboxWyniki.Wyczyść;

kończyć się;

procedura TformMain.Button1Click (Sender: TObject);

I: liczba całkowita;

S: sznurek;

zaczynać

ButnLookup.Enabled: = prawda; próbować

LboxWyniki.Wyczyść;

z Klientem zaczynaj

Połączyć; próbować

LboxResults.Items .Add (ReadLn);

for i: = 0 do memoInput.Lines .Count - 1 do początku

WriteLn („Kod pocztowy” + memoInput.Lines [i]);

LboxResults.Items .Add (memoInput.Lines [i]);

S: = OdczytLn;

jeśli s = "" to zacznij

S: = „- Nie znaleziono wpisu dla tego kodu pocztowego”.;

kończyć się;

LboxResults.Items .Add(s);

LboxResults.Items .Add ("");

kończyć się;

WriteLn („Zakończ”);

wreszcie Odłącz; kończyć się;

kończyć się;

wreszcie butnLookup.Enabled: = true; kończyć się;

kończyć się;

kończyć się.


Jedynymi częściami specyficznymi dla komponentu klienta są metoda Button1Click.
W formularzu znajduje się składnik Client typu TIdTCPClient. Zmieniono następujące właściwości: · Host = 127.0.0.1 — serwer znajduje się na tym samym komputerze co klient. Port = 6000 - Port serwera
Metoda Button1Click jest skojarzona ze zdarzeniem OnClick składnika Button1. Po kliknięciu przycisku ta metoda jest wywoływana. Część Indy tej metody można zredukować do następujących: 1. Połącz się z serwerem (Połącz;) 1. Odczytaj powitanie z serwera. 1.Dla każdej linii wprowadzonej przez użytkownika w TMemo: 1.Wyślij żądanie do serwera (WriteLn („ZipCode” + memoInput.Lines [i]);) 1.Odczytaj odpowiedź z serwera (s: = ReadLn; ) 1.Wyślij polecenie Quit (WriteLn ("Quit");) 1.Rozłącz (Rozłącz;)
Testowanie
Ten przykład został przetestowany i działa z zainstalowanym protokołem TCP/IP. Możesz go zmienić, aby działał przez sieć z jednego komputera na drugi. Uruchamiając serwer na innym komputerze i zmieniając nazwę serwera lub IP na kliencie.
Aby przetestować projekty, skompiluj i uruchom serwer. Następnie skompiluj i uruchom klienta. Wprowadź kod pocztowy w polu notatki i naciśnij klawisz wyszukiwania.
Debugowanie
Protokoły tekstowe są bardzo łatwe do debugowania, ponieważ można je zweryfikować za pomocą usługi Telnet. Aby to zrobić, wystarczy znać port serwera. Serwer wyszukiwania kodu pocztowego nasłuchuje na porcie 6000.
Ponownie uruchom serwer wyszukiwania kodu pocztowego. Następnie otwórz konsolę (jak okno Dos). Teraz wpisz:
telnet 127.0.0.1 6000
Jesteś teraz połączony z serwerem. Niektóre serwery wysyłają przy tym wiadomość powitalną. Niektórzy nie. Nie zobaczysz linii, które wprowadzisz. Większość serwerów nie odbija echa, aby zaoszczędzić przepustowość. Możesz jednak zmienić ustawienia telnet, ustawiając parametr „Echo On”. W różnych klientach telnet odbywa się to na różne sposoby, a niektórzy w ogóle nie mają takiej możliwości. Teraz wpisz:
kod pocztowy 37642
Zobaczysz odpowiedź serwera:
WZGÓRZE KOŚCIELNE, TN
Aby rozłączyć się z serwerem, wprowadź:
zrezygnować
Przykład 2 - dostęp do bazy danych
Ten przykład emuluje serwer, który musi wykonywać zadania blokowania inne niż wywołania gniazd. Wiele serwerów jest zmuszonych do pracy w takich warunkach. Serwery, które potrzebują dostępu do bazy danych, wywołania procedur zewnętrznych lub obliczeń często nie mogą przerwać tych wywołań, ponieważ są to wywołania zewnętrzne lub z powodu ich złożoności. Odniesienia do bazy nie można rozbić na małe kawałki i deweloper musi poczekać na zakończenie operacji z bazą. Jest to cecha nie tylko wywołań baz danych, ale także innych operacji, takich jak kompresja, obliczenia i inne tego samego rodzaju przetwarzanie.
Dla celów demonstracyjnych załóżmy, że serwer wykonuje wywołanie bazy danych, które trwa 5 sekund. Dla uproszczenia zróbmy to po prostu z pauzą, użyj do tego funkcji Sleep (5000), zamiast faktycznie dzwonić.
Ten przykład wymaga również mniej szczegółów niż poprzedni, ponieważ wiele pojęć nie jest jeszcze zrozumiałych.
Źródło

jednostka główna;

berło

używa

Windows, komunikaty, narzędzia SysUtils, klasy, grafika, kontrolki, formularze, okna dialogowe,

IdBaseComponent, IdComponent, IdTCPServer;

rodzaj

TformMain = klasa (TForm)

IdTCPServer1: TIdTCPServer;

procedura IdTCPServer1Execute (AThread: TIdPeerThread);

prywatny

publiczny

kończyć się;

FormMain: TformMain;

realizacja

(R * .DFM)

procedura TformMain.IdTCPServer1Execute (AThread: TIdPeerThread);

I: liczba całkowita;

zaczynać

z AThread.Connection zaczyna się

WriteLn ("Witaj. Serwer DB gotowy.");

I: = StrToIntDef (OdczytLn, 0);

// Sleep jest zastępowany długim DB lub innym wywołaniem

sen (5000);

WriteLn (IntToStr (i * 7);

kończyć się;

kończyć się;

kończyć się.

Ponieważ zdarzenie Execute występuje w kontekście wątku, kod przetwarzania może mieć dowolną długość. Każdy klient ma własny wątek i nie blokuje innych klientów.
Testowanie
Aby przetestować serwer DB, skompiluj go i uruchom. Połącz się z nim przez Telnet na porcie 6001. Serwer odpowie wiadomością powitalną. Wpisz numer. Serwer „przetworzy” Twoje żądanie i odpowie w ciągu 5 sekund.

Podobał Ci się artykuł? Podziel się z przyjaciółmi!
czy było to pomocne?
tak
Nie
Dziekuję za odpowiedź!
Coś poszło nie tak i Twój głos nie został policzony.
Dziękuję Ci. Twoja wiadomość została wysłana
Znalazłeś błąd w tekście?
Zaznacz to, kliknij Ctrl + Enter i wszystko naprawimy!