Home > Delphi | Indy Kütüphanesi | Network Programlama > Indy ile Network Programlama 1 – Giriş

Indy ile Network Programlama 1 – Giriş

Posted on 08 Nisan 2007 | 14 Yorum

Bundan önce Mustafa arkadaşım, Winsock kullanarak, ağ üzerinden nasıl iletişim kurabilceğimizi göstermişti. Å?imdi dilerseniz biraz daha ileri gidelim ve Indy (indi) kullanarak network üzerinde nasıl işlem yapabileceğimizi görelim. Indy bileşenleri, Delphi ile birlikte gelen ve .NET(D.NET ve VS), C++ Builder, Kylix ve Lazarus gibi bir çok geliştirme ortamına destek veren ağ bileşenlerinden oluşur. Bir çok noktada, kendiniz uğraşsanız çok fazla kafa ağrıtacağınız yerleri, Indy halletmiş ve kolaylaştırıp, basitleştirerek bizlere sunmuştur. Eğer ağ üzerinde gerçekten ciddi bir şeyler yapmak istiyorsanız Indy kullanmanız kaçınılmazdır. Ayrıca .Net kullanıcısı iseniz, .Net’de socket desteği olduğu halde Indy’nin neden .Net desteği verdiğini de merak edebilirsiniz. Ayrıca neden Indy’ye ihtiyaç vardır, onu da göreceğiz.

Bölüm 1 – Giriş

Bölüm 2 – Okuma ve Yazma

Bölüm 3 – Server

Niçin Indy?

İlk başta buradan başlayalım. DotNet kullanıcılarının genelde sordukları soru bu. DotNet’de socket desteği varken neden Indy kullanacağım?

  • Daha Fazla Protokol: Indy, herhangi bir kütüphaneden daha fazla protokol desteğine sahiptir. Bu fazlalık 120 kadar protokol ve internet standardını barındırır. Indy ve .NET’in özellik karşılaştırmalarına buradan bakabilirsiniz.
  • Sağlamlık ve Güç: Indy protokollerinin herbiri barındırdığı destekler sayesinde güç kazanmıştır. Mesela SMTP portokolü, MIME, Base64, BinHex, QP, XXE, ve UUE gibi aklınıza gelebilecek bir çok encoding tipine destek vermektedir. FTP için dahili dosya parser’ı bilinen bütün dosya listeleme formatlarını destekler. Mevcut bir protokole Indy ile yeni bir özellik eklemek neredeyse gereksizdir ve çok az rastlanır.
  • Kullanım Kolaylığı: Indy, ağ kullanımını çok kolaylaştırmıştır. Çünkü kullandığı engelleme modeli sayesinde sizi event tabanlı durum makinalarından kurtarıp, sanki bir dosyaya erişir gibi, bütün isteklerinize cevap verir.
  • Indy, Bedavadır: Herhangibir şekilde dağıtmanız, kullanmanız veya bir uygulama yapıp satmanız tamamen bedavadır.
  • Indy, Açık Kaynak Kodludur: Indy, işinde uzman bir çok programcının oluşturduğu büyük bir programlama ekbinin çabaları ile geliştirilmektedir.
  • Kaynak Kod: Yukarıdaki ile benzer olarak, kaynakları görebilmeniz, bir işin nasıl yapıldığı hakkında size geniş bir bilgi de sunacaktır. İçlerde olan bir şeyi tahmin etmeye gerek kalmadan, bazı şeylerin yolunda gitmediğinde deneme yanılma yöntemine başvurmadan, kaynak kodları inceleyebilir ve kodlar ile debug yapabilirsiniz. Tam kaynak kod, tam bilgi, tam güç.
  • Kendini Kanıtlamıştır: Evet, Indy kendini kanıtlamış bir kütüphanedir. 10 yılı aşkındır, onbinlerce programcı tarafından milyonlarca kurulum gerçekleştirmiştir. Indy kütüphanesini, dilerseniz küçük bir iş yerinde, dilerseniz daha büyüğünde, dilerseniz devlet işlerinde ya da daha fazlasında kullanabilirsiniz.
  • Esneklik: Indy’nin her katmanı takılıp çıkarılabilir cinstendir. RFC cevapları, şifreleme, yetkilendirme, kodlama ve daha fazlası bu kategoriye girer.
  • Taşınabilirlik: Indy kütüphanesi, Win32, DotNet ve Linux için uyumlu olduğu gibi, C#, C++, Delphi, JScript ve Visual Basic dillerini de destekler. Tek kanyak kod ile bu platformların hepsine destek verir.

Bu girişten sonra belirtmek isterimki vereceğimiz kodlar Delphi üzerinden olacaktır. Ama son açıkladığımız maddenin avantajı ile aynı şeyleri kendi geliştirme ortamınız için de yapabileceksiniz.

Giriş İçin Bir Kaç Terim:

Eğer hayatınızda hiç network programlamaya bulaşmamış iseniz veya aşağıdaki terimlerin ne olduğunu bilmiyorsanız, internet üzerinde kısa bir araştırma yapmanızı öneririm. Bu terimler zaten bir çok yerde tekrar tekrar bahesdilmiş durumda. Bunları öğrenmelisiniz, çünkü bunlar ağ programlamanın temelini oluşturmaktadır. Bu makalemizde bu terimleri anlatmayacağız. Terimlerin fazlalığına bakıp şevkinizi yitirmeyin. Tanımları toplasanız ancak bir sayfa kadar olacaktır, fazla değil. Çoğunu da bildiğinizi zannediyorum.

TCP/IP, Client, Server, IP Adresi, Port, Protokol(Protocol), Socket, Host Name, DNS, TCP ve UDP, ICMP, Localhost(Loopback), Ping, TraceRoute, LAN, WAN, RFC, Thread(Kanallar) ve Fork, Winsock, Stack, Network Byte Order(LSB, MSB).

Indy’ye Giriş:

Client tarafında bağlantı, TCP/IP stack detayları programcıdan gizlenerek, yüksek seviye soyutlama sağlanır. Yani "Indy Client" bileşenlerinden herhangi birisi ile basit bir şekilde şöyle bir bağlantı kurabilirsiniz.

with MyIndyClient do
begin
  Host := 'www.diyezon.com';
  Port := 4443;
  Connect;
  try
    //Buraya iletişim kodlarınız gelecek
  finally
    Disconnect;
  end;
end;

Bu kadar basit. Server tarafında ise, Indy Server bileşenleri, programın ana kanalı dışında yeni bir kanal(thread) oluşturarak, gelen client isteklerini dinler. Bu dinleme sonrasında, ayrılmış olan her olay(event), kanalın içeriği(context) olarak tetiklenir. Size kalan, sadece bu içeriği kullanarak Client ile iletişim kurmaktır.

Indy, bu iletişim esnasında sıkça kanal sitemini kullanır. Bu, Client ve Server için büyük kolaylık sağlamaktadır. Bununla birlikte "engellemeyen" socketler de kanallanabilir. Ama "engelleyen" socketlere göre fazladan işlem gerektirdiği için avantaj sağlamamaktadır.

Engelleyen(Blocking) ve Engellemeyen(Non-Blocking) Socketler

Windows altında socket programlamada iki tip model vardır. Engelleyen ve engellemeyen socketler. Bazen bunlara eş zamanlı(synchronous, engelleyen) ve eş zamansız(asynchronous, engellemeyen) olarak da isim verilmektedir. Bu makalemizde engelleyen ve engellemeyen olarak isim vereceğiz.

Unix altında sadece engelleyen socketler desteklenmektedir.

Bunun dışında tanımlanmış portlar ve bindirilmiş giriş çıkışlar ile yapılan bir kaç model vardır. Ama bunlar daha fazla kod ve ileri düzey bilgi gerektirir. Ve cross-platform olmadıklarından, işletim sisteminden, işletim sistemine farklılık arzeder. Indy 10, bu modelleri de desteklemektedir.

Engelleyen Socketler:

Indy, engelleyen socket çağrımlarını kullanır. Engelleme, daha çok bir dosyaya yazma ve bir dosyayı okuma gibidir. Bir veriyi okuduğunuzda ya da yazdığınızda, operasyon tamamlanana kadar fonksiyon çıktı vermeyecektir. Socketlerle çalışmanın dosyalardan farkı, ağ hızından dolayı verileri hemen yazıp okuyamamanızdır. Her nekadar 1000 Mbit’lik ethernetler çıksa da, şu anki çoğu ağ ve modem hardiskten hızlı çalışamamaktadır.

Indy ile birlikte, bir socket’e bağlanma, sadece Connect metodunu çağırmak ve cevabını beklemek kadar basittir. Eğer Connect metodu başarılı olursa, bağlantı olduğunda dönecektir. Yani Connect komutu bağlanana kadar altındaki komutlara geçilmeyecek ve kod akışını engelleyecektir. Eğer bağlantı başarısız olursa bir Exception(istisna) gönderecektir. Bu Exception‘ların düşünülenin aksine her biri bir hata değildir. Mesela bağlantı sağlanamaz ve Delphi debug işlemini durdurup mesela EIdAlreadyConnected istisnasını gösterir. Ama bu hata değil, zaten bağlı olduğunuzu ifade eden bir bilgilendirmedir.

Engellemeyen Socketler:

Bu tip socketler, sistem olayları ile çalışırlar. Bağlantı yapılıp, ne zaman tamamlanırsa, o zaman bir olay tetiklenir.

Mesela, bir socketi bağlamak için Connect komutunu kullanıyoruz. Socket daha bağlanmadan, Connect komutu dönecek ve devamındaki kodlar çalıştırılacaktır. Socket bağlandığı an, bir olay tetiklenecektir. Bu, iletişim işleminin bir çok prosedüre ayrılmasına veya döngü havuzlarını kullanmaya sebep olacaktır.

Engelleme Kötü Değildir!

Engelleme, belli bir zamana kadar yanlış temeller üzerine inşa edilmiştir. Bu yüzden engellemenin yanlış olduğuna dair yanlış bir fikir ortaya çıkmıştır. Ama sanılanın aksine, engelleme kötü değildir.

Unix API’leri, Windows’a taşındığı zaman Winsock ismini aldı. Winsock, "Windows Socket"’in kısaltılmış halidir. Unix’den Windows’a taşınma esnasında hemen bir fark ortaya çıktı. Unix’de Fork denen bir kavram vardır. Bu Multi-threading’e benzer bir sistemdir. Ama fark olarak, kanalların ayrılığı yerine işlemlerin ayrılığı söz konusudur. Unix client ve server’ları her socket için fork işlemlerini kullanır. Bu işlemler bağımsız olarak çalıştırılırlar ve engelleyen socketleri kullanırlar.

Windows 3.1 etkin olarak fork kullanamıyordu ve multi-tasking ve diğer gerekli şeylerden de yoksundu. Windows 3.1, thread’leri de desteklemiyordu. Engelleyen socket’leri kullanmak, uygulamaları kilitleyip donduruyordu. Bu istenilmeyen durumu ortadan kaldırmak için, Win3.x’ de WinSock’ a engellemeyen socket modeli eklendi. Bu eklenti, bilindik socket programlamadan farklı bir yapıda idi.

Windows NT ve 95 ile artık Windows, multi-task ve thread’lere sahip oldu. Ama bu zamana kadar, programcılar engelleyen socketlerin kötü ve yanlış olduğu görüşüne kapıldılar.

Engellemenin Avantajları

  • Programlama işlemi çok kolaydır.
  • Cross-Platform’dur. Yani Unix’den, Windows’a bütün işletim sistemlerinde çalışır.
  • Kanallarla(threads) birlikte rahat bir şekilde kullanılabilir.
  • Windows Mesajlarına bağlı değildir. Windows Mesajları, bir çok bağlantı söz konusu olduğunda sıkışık durumlar ortaya çıkaracaktır. Ama kanallar kullanıldığında bu sorun yaşanmayacaktır.

Engellemenin Dezavantakları

  • Client tarafında donmalar yaşanabilir. Bu donmalar, uygulamanın diğer mesajlarını engellediği için, pencerenin tekrar çizilmesi, güncellenmesi gibi işlemleri de engelleyecektir. Ama bu işlem kanallar ile ortadan kalkabilecek bir durumdur. Indy, TIdAntiFreeze isminde barındırdığı bir bileşen ile bu dezavantajı kaldırarak, engelleyen socketlerin tüm avantajlarından istifade etmemizi sağlar.

Engellememenin Avantajları

  • Olay tabanlı olduğundan Client tarafından donma gerçekleştirmeyecektir.
  • Mult-tasking ile ekstra thread kullanmadan tek thread içinde bir çok socket bağlanabilir.
  • Thread kullanılmadığından çok çok fazla socket bağlantılarında memory ve CPU kullanımı düşük olacaktır.

Engelememenin Dezavantajları

  • Programlanması çok daha zor ve karışıktır. Olaylar ya da havuzlama tekniği ile işlerin takibi daha da zorlaşır. Kodlar çok fazla prosedüre ayrılır. Programın tekrar düzenlenmesi zor olduğu gibi, bir çok bug’a da davetiye çıkaracaktır.

Karşılaştırma

Socket programlamaya başlayanlar için Indy, gerçekten çok kolay ve rahattır. Ama önceden socket programlama ile uğraşmışlar için Indy bir tökezleme olabilir. Çünkü Indy farklıdır. Bu diğer yaklaşımların yanlış olduğu anlamına gelmez. Sadece Indy farklıdır o kadar. Diğer socket kütüphaneleri ile Indy arasındaki fark, bir yemeği, bir ocak üzerinde ve bir mikrodalgada pişirmek gibi farklıdır.

Indy’nin programlama mantığını anlatabilmek için bir dosya yazıp, okuma işlemini gerçekleştireceğiz. Bu makaleyi okuduğunuza göre, basit bir dosyaya yazıp okuma işlemini bildiğinizi farz ediyorum. Bu da demek oluyorki, bu makaleyi hiç bir Visual Basic kullanıcısı okumuyor. :)

Dosyalar ve Socketler

Dosya işlemleri ve socketler arasındaki temel fark sadece hızdır. Tabi ki, dosya erişimi her zaman hızlı da değildir. Network sürücüleri, floppy diskler, yedekleme üniteleri gibi ortamlar geç cevap sürelerine sahiptirler.

Yapacağımız işlem çok basit:

  • Dosyayı aç
  • Veriyi yaz
  • Dosyayı kapat

Engelleyen Dosya Yazımı

Engelleyen dosya yazım işlemi şöyle bir şeydir:

procedure TForm1.Button1Click(Sender: TObject);
var
  str: string;
begin
  str := 'Yazılacak bilgi';
  try
    //Dosyayı Aç
    with TFileStream.Create('deneme.txt', fmCreate) do
      try
        WriteBuffer(str[1], Length(str)); //Veriyi yaz
      finally
        Free; //Dosyayı kapat
    end;
  except
  end;
end;

Görüldüğü gibi işlem çok basit. Aç, yaz ve işin bitince kapat.

Engellemeyen Dosya Yazımı

Aslında özel bir kaç işlem yapmadan böyle bir şey yapılması olası değil. Ama olsaydı aşağıdaki gibi bir şey olurdu. TBlockingFile gibi hayali bir bileşenimiz olduğunu varsayalım:
procedure TForm1.Button1Click(Sender: TObject);
begin
  BlockingFile1.FileName := 'deneme.txt';
  BlockingFile1.Open;
end;

procedure TForm1.BlockingFile1OnOpen(Sender: TObject);
var
  i: integer;
begin
  FWriteData := 'Yazılacak Bilgi';
  i := BlockingFile1.Write(FWriteData);
  Delete(FWriteData, 1, i);
end;

procedure TForm1.BlockingFile1OnWrite(Sender: TObject);
var
  i: integer;
begin
  i := BlockingFile1.Write(FWriteData);
  Delete(FWriteData, 1, i);
  if Length(FWriteData) = 0 then
  begin
    BlockingFile1.Close;
  end;
end;

procedure TForm1.BlockingFile1OnClose(Sender: TObject);
begin
  Button1.Enabled := True;
end;

Biraz zaman ayırıp neler döndüğüne bir göz atın. Eğer önceden engellemeyen socketleri kullanmış birisi iseniz yukarıdakinin ne olduğunu anlayacaksınız.

Görüldüğü gibi engellemeyen sürümü daha karmaşık ve anlaşılması zor.

Aynen Dosyalar Gibi

Indy’i kullanmak, aynen dosyalar gibidir. Indy, kolaydır, çünkü yazma ve okuma işlemleri için tonlarca metod vardır. Dosya yazımına eş değerde Indy kodları şu şekilde olacaktır:

with MyIndyClient do
begin
  Connect;
  try
    WriteLn('Sunucuya selamlar..');
  finally
    Disconnect;
  end;
end;

Dosyalardaki Open yerine Connect ve Close yerine de Disconnect komutlarını koyarak rahat bir şekilde bağlantı kurabilirsiniz.

Gelecek bölümde Okuma ve Yazma üzerine gideceğiz. Hazır olduğunuzda Bölüm 2‘den devam edebilirsiniz.

vesselam.

Fatih Tolga Ata © 2007

Kaynaklar:

Bölüm 1 – Giriş

Bölüm 2 – Okuma ve Yazma

Bölüm 3 – Server

» Tags: , , , , , , , , , , , , ,

14 Yorum

  • At 2007.04.09 08:18, Mustafa KUTLU said:

    Ellerine sağlık Fatih. Çok güzel bir kaynak olmuş. Nice güzel yazılarını bekliyor olacağız, uzun süre sonunda sessizliğinin bozulması hoş oldu :) Tabii birde hala sesi çıkmayan birileri; doğanbirleri var :)

    • At 2007.04.21 11:23, Mustafa Kahraman said:

      Hocam

      Emeğinize sağlık güzel makale…

      • At 2007.04.23 00:24, kadir huysal said:

        hocam süpersin ya bunun gibi bilgilere çok ihtiyaç var indyler hakkında yazılarının devamını sabırsızlıkla bekliyorum.Delphi İndy component tabında bilmediğim o kadar çok şey varki umarım bunlarada örnekler ve anlatımlar verirsin.Çalışmanda başarılar.

        • At 2007.04.23 12:41, Fatih Tolga Ata said:

          Yararlı olduysa ne mutlu.. Vaktim oldukça bu konuda yazmaya çalışacağım.

          Kolay gelsin.

          • At 2007.05.14 00:48, Hakan MÜÅ?TAK said:

            ellerine sağlık

            • At 2007.06.23 13:26, Murat Doğan Çoruh said:

              Gördüğüm en güzel türkçe socket makalelerinden biri. Helal olsun.

              • At 2007.08.06 14:25, ibrahim kutluay said:

                Güzel makale. Tebirkler ve devamını diliyoruz…

                Bence SQL konusuna eğilmelisin. Örneğin detaylı sql kullanımı konusunda pek bir kaynak yok. Join filan dedimi o kadar yalın geçiyorki kitaplar

                • At 2007.09.24 22:18, Hüseyin Küçük said:

                  Hocam, teşekkür ederim… Birinci bölümü büyük bir zevkle okudum, bu mesajı gönderip hemen ikinci bölüme geçiyorum… Teşekkürler…

                  • At 2007.11.03 13:45, Mustafa Yalçın said:

                    Teşekkür ederim hocam. Indy dışında diğer network bileşenleri ile bir sürü kod yazmış ama Indy’yi anlayamamıştım. Sayende olayı kaptım :)

                    • At 2008.02.07 16:10, kont61 said:

                      Anlatımlarınız çok hoş. Okudukça okuyasım geldi. Bu blog u yeni keşfettim sürekli takip etmeye çalışacağım. Emeği geçen herkese bol bol teşekkür ederim.

                      • At 2008.04.22 16:40, teset said:

                        Yazınız bana faydalı oldu.
                        Teşekkürler.

                        Okuyan olur diye basit bişey sormak istiyorum. LAN içinden dışarı çıkan tüm clientlar aynı ip numarası ile çıkacaklar. İnternet üzerinde bu pclerin bağlandığı bir server bu client ları nasıl ayırıyor.

                        Teşekkürler.

                        • At 2008.04.23 11:00, Fatih Tolga Ata said:

                          Server’ı siz yazdığınız sürece client’ı ayıramamak gibi bir derdiniz yok. Çünkü server’ın protokol yapısını sonuçta siz belirlemiş oluyorsunuz.

                          • At 2008.04.29 14:15, Fatih Demirer said:

                            anlatımınız oldukca verimli olmuş. Ancak insanlar hep daha fazlasını ve daha fazla ipucunu ister. aynı ben gibi :) mesela client/server uygulamalarında servera bağlanan clientleri ayırma oldukca zor. IRC sunucuları buna bir yöntem bulmuş sanırım ama yaptıkları şeyde cok karışık geldi. mesela anlatımınıza ek olarak daha ayrıntılı bir server yazılımı hakkında bilgi verirseniz sevinirim.

                            anlatılan bir cok server uygulamasını zaten biliyoruz ve ezberledik. ancak çoğu anlatılan uygulamalarda 2 adet client arasında sunucu üzerinden yazışmayı anlatan yok. ben ali isimli arkadaşıma yazacağım ama yazdığım ali isimli arkadaşın bağlantısını sunucuda nasıl bulacağım. ıp den buldum diyelim, arkadaşım cafedeyse o ıpde bircok kişi sunucuda olabilir. bu tür ayrıntılarada deyinirseniz sevinirim. iyi çalışmalar dilerim.

                            • At 2011.03.13 03:05, Nazım said:

                              merhaba
                              bir program kullanıyorum. bu program 1234 portundan sürekli tcp ile data gönderiyor. gelen data satırları “|” karakteri ile ayrılmış. okuduğum dökümanlarda Tclientsocket kullanmayın diyor ve indy öenriyor (bu sitedede aynı bilgi var). indy’de onRead eventi yok. ne yapmalıyım yardımcı olabilecek biri var mı?
                              Şimdiden teşkkürler
                              Nazım nkeskin@komtere.com

                              (Required)
                              (Required, will not be published)

                              Switch to our mobile site