Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Delphi ve Protocol Buffers
#1
Sık sık ihtiyaç duyduğumuz bir olaydır; yazdığımız iki uygulama arasında veri paylaşmak. İster iki uygulama da Delphi’de yazılmış olsun, ister farklı dillerde yazılmış olsun veri paylaşmak gerektiğinde verinin gönderiliş/alış şekli önemlidir. Bu gibi durumlarda verinin serileştirilmesi gerekir. Bunlardan en yaygın olanı XML ve JSON’dur.
Ben başka bir alternatiften daha söz etmek istiyorum: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız..
  • Google tarafından geliştirilmiştir.
  • Kısaca Protobuf olarak adlandırılır.
  • Açık kaynak kodludur: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
  • Resmi olarak C++, C#, Java, Python, Objective-C, PHP, Javascript, GO, Ruby desteği mevcuttur.
  • Daha az yer kaplar, daha hızlıdır (Performans karşılaştırmaları için Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. bakabilirsiniz)
  • Google’ın kendi uygulamaları arasındaki veri alışverişi için kullanıldığı gibi, Twitter, Spotify vs. dünya genelinde tanınmış bir çok firma tarafından kullanılmaktadır.
  • Bir çoğumuzun başını ağrıtan JSON-XML parse işlemlerinden kurtulmuş oluruz.


Örneğin siz uygulamanızdan kişi bilgilerini başka uygulamaya göndermek istiyorsunuz. Bunu Delphi’deki bir class, bir record yada veri tabanından alınan bir kayıt gibi düşünebilirsiniz. Kişinin Id’si, ismi, email adresi ve telefon numara(lar)ı olduğunu düşünelim.

Öncelikle bu veri yapısını Protobuf’ta tanımlamamız gerekir. Bunun için .proto uzantılı dosyalar kullanılır. Basit bir şeması vardır. Bizim örneğimiz için oluşturmamız gereken proto dosyası şöyle olabilir:
syntax = "proto3";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
  repeated string phonenumber = 4;
}
Görüldüğü gibi basit bir yapısı var, okunabilirliği çok kolay. Ama istenilirse çok detaylı veri yapıları oluşturulabilir. Detaylar için şuraya bakabilirsiniz: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.

Bir kişinin birden fazla telefon numarası olabileceği için phonenumber alanımızı repeated tanımladık.
Her alanımızın sonunda tekil bir numara veriyoruz. Bu numaralar tekil olmalı ve daha sonra değiştirilmemeli.
Bir message içinde başka bir message kullanabiliriz(nested).

Bundan sonra yapılması gereken; bu mesajı hangi programlama dilinde kullanmak istiyorsak onun için derlemek. Google bunun için protoc.exe adında bir araç geliştirmiş. Protobuf’ın Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.nden istediğiniz işletim sistemi için indirme yapabilirsiniz.

Yukarıdaki örneğimizi person.proto adıyla kaydettiğimizi ve bu mesajları Java ve C# içinde kullanacağımızı varsayarsak:

protoc.exe  person.proto  --java_out=DIR_PATH  --csharp_out=DIR_PATH

Bu komutu çalıştırdığımızda DIR_PATH klasörü altında hem Java hem de C# dosyalarının oluştuğu görülür.


Yukarıda yazdığım gibi, desteklenen diller arasında maalesef Delphi yok Sad (Artık bu tarz şeylere pek de şaşırmıyoruz)

Delphi gibi resmi olarak desteklenmeyen diller için bir çok üçüncü parti çözümler üretilmiş ve onlar Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. listelenmiştir. Ben Delphi için şunu kullanıyorum: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.

Bu kütüphaneyi indirip ProtoBufGenerator.exe'yi kullanarak yukarıda protoc.exe’nin yaptığı işlemi Delphi için yapabiliriz. Yani proto dosyasından pas dosyası üretebiliriz.
Yukarıdaki örnekten devam edecek olursak; person.proto'dan person.pas dosyasını elde ettik diyelim. Bu dosya içinde bizim Person mesajımız için TPerson sınıfının otomatik olarak oluşturulduğunu göreceksiniz.(Üstelik sınıf içinde yapılabilecek işlemler de otomatik olarak hazır Wink )

Basit bir sunucu-istemci örneği hazırladım. TCPClient ile mesajımız gönderip TCPServer ile okunuyor.

sonuc.gif


Client’an mesaj gönderme kısmı;
procedure TForm2.Button1Click(Sender: TObject);
var
 Person: TPerson;
 MS: TMemoryStream;
begin
 MS := TMemoryStream.Create;
 Person := TPerson.Create;
 try
   Person.id := 10;
   Person.name := 'DelphiCan';
   Person.email := 'info@delphican.com';
   Person.phonenumberList.Add('05551234567');
   Person.phonenumberList.Add('02167777777');
   Person.phonenumberList.Add('7654321');
   Person.SaveToStream(MS);

   IdTCPClient1.Socket.Write(MS, 0, True);
 finally
   Person.Free;
   MS.Free;
 end;
end;

Sunucuda mesajı alma kısmı:
procedure TForm1. IdTCPServer1Execute(AContext: TIdContext);
var
 aPerson: TPerson;
 MS: TMemoryStream;
begin
 MS := TMemoryStream.Create;
 aPerson := TPerson.Create;
 try
   AContext.Connection.Socket.ReadStream(MS);
   aPerson.LoadFromStream(MS);
   // burada kişi bilgilerine erişebiliriz
   // aPerson.Id yada aPerson.name gibi
   // kişinin telefon numarası sayısı aPerson.phonenumberList.Count
   // kişinin ilk telefon numarası aPerson.phonenumberList[0]
 finally
   aPerson.Free;
   MS.Free;
 end;
end;

Görüldüğü gibi XML yada JSON parse’deki zahmetli işlerle uğraşmak zorunda kalmıyoruz. Her şey otomatik olarak oluşturulmuş sınıflarımız içerisinde mevcut. (Mesela yukaridaki örnekte telefon numarlarının tutulduğu phonenumberList otomatik oluşturulmuştur)
Bu kullanımın güzelliği daha karmaşık mesajlar göndermek istediğinizde ortaya çıkacaktır. Proto dosyası içinde message içinde başka bir message (nested) kullanabilmeniz size çok büyük esneklik katacaktır.
Protobuf’ın bir başka güzelliği ise; mesaj içinde değişiklik yaptığınızda eski versiyon mesajlarınızla da çalışmaya devam edebiliyorsunuz! Yeni bir alan ekleyebilirsiniz, var olanı silebilirsiniz vs.

Özellikle farklı programlama dilleri arasında mesajlaşma gerektiğinde çok daha faydalı olduğunu görebilirsiniz. Karşı taraf hangi dili kullanıyorsa protoc.exe ile o dil için çıktı üretip karşı tarafa bunu veriyoruz.


ProtoBuf böyle kısa bir makaleye sığdırılamayacak kadar güzel ve detaylı bir projedir. Ben sadece giriş mahiyetinde bilgilendirme yapmaya çalıştım. Umarım ilgilenen çıkar Blush

Örnek projenin kaynak kodlarını buradan indirebilirsiniz:
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
There's no place like 127.0.0.1
WWW
Cevapla
#2
Hocam çok teşekkür ederim. harika bir anlatım olmuş. Elinize, emeğinize sağlık.
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Cevapla
#3
Teşekkürler faydalı ve güzel bir paylaşım için.
Cevapla
#4
Ellerine sağlık güzel kardeşim. Mobil ortamdan bakıyorum, dolayısı ile detaylı bir inceleme şansım olmadı; lâkin bizim Delphi içinde tanımladığımız sınıfları Rest.Json unit’i içindeki TJson sınıfı ile serialize/deserialize etmek gözüme daha kolay göründü.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#5
Elinize sağlık hocam, güzel anlatım.
WWW
Cevapla
#6
(27-05-2019, Saat: 19:33)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Ellerine sağlık güzel kardeşim. Mobil ortamdan bakıyorum, dolayısı ile detaylı bir inceleme şansım olmadı; lâkin bizim Delphi içinde tanımladığımız sınıfları Rest.Json unit’i içindeki TJson sınıfı ile serialize/deserialize etmek gözüme daha kolay göründü.

Alışınca tadından yenmez Big Grin

Kolaylıktan ziyade ProtoBuf'ın asıl avantajı az yer kaplaması ve hızı. Sıradan bir proje için bunlar önem arz etmeyebilir ama Google Maps gibi bir projede bu yüzden ProtoBuf kullanılır. Yada giderek büyük bir hızla yayılan IOT dünyasında, büyük çapta bir projeye girildiğinde, sahada kullanılan binlerce cihazdan gelen/giden veri düşünüldüğünde harcanan bandwidth'in ne kadar önemli olduğu malumdur. 

Ben ProtoBuf'tan bahsettim, benden günah gitti Big Grin Big Grin
There's no place like 127.0.0.1
WWW
Cevapla
#7
Elinize saglik
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Delphi'de Indy SMTP ile e-mail gönderme. (GMail, Yandex, Yahoo vb.) csunguray 15 3.050 26-06-2019, Saat: 13:59
Son Yorum: csunguray
  Delphi LZW Algoritması narkotik 2 598 14-06-2019, Saat: 09:19
Son Yorum: frmman
  Delphi'de BreakPoint (durma noktası) işaretinin yanlış satırda görünmesi csunguray 1 568 17-12-2018, Saat: 00:40
Son Yorum: Bay_Y
  Delphi IDE'sine Eklenti Yapmak - 2 SimaWB 27 4.478 04-12-2018, Saat: 10:25
Son Yorum: ssahinoglu
  Delphi'de Inno Setup | Sorgulu Uninstall İşlemi Halil Han Badem 13 1.768 17-11-2018, Saat: 19:50
Son Yorum: sabanakman



Konuyu Okuyanlar: 1 Ziyaretçi