Makale Özeti

Bu makale serimizde .Net Compact Framework 2.0 üzerinde Mobil Cihazlarda Socket’ ler üzerinden haberleşen bir Chat uygulaması geliştireceğiz. İlk durağımız sunucu uygulaması.

Makale

Genel hatlarıyla makalemizin konusunun başlığına bundan yaklaşık 3-4 sene önce bakılsaydı birçok uygulama geliştirici için böyle bir sistemi gerçekleştirmek ütopik ; belkide, imkansız olarak düşünülebilirdi. Mobil Cihazlar’ dan öte standart Windows işletim sistemimiz üzerinde Socket’ ler üzerinden haberleşip birbirleri arasında veri transferi gerçekleştiren uygulamalar geliştirebilemek için bile bundan kısa bir süre öncesine kadar yüksek bir programlama bilgisi gerektirmekte ; herşeyden öte işletim sistemimiz üzerindeki API (Application Programming Interface) Fonksiyonlarını bilmemizi gerektirmekdeydi.

Olaya bu açıdan bakıldığında Socket programlama her zaman uygulama geliştiriciler için bir problem ; en azından bir önceki paragrafta belirtildiği üzere yüksek programlama bilgisi gerektiren bir kavram olmuştur.

2000 yılında .Net Framework “dünyası” ile tanıştığımızda ise neredeyse tüm sıkıntılarımız sona ermiş, yepyeni bir platform ile karşı karşıya kalmıştık. Az önce üzerinde konuştuğumuz yüksek porgramlama bilgisi gerektiren birçok kavramı .Net Framework üzerinde çok daha kolay bir şekilde gerçekleştirmenin verdiği rahatlık ve esneklik ile çok daha büyük ölçekli ve hatasız projeler günümüzde birçok platform üzerinde geliştirilmektedir.

Konuyu bu noktada toparlamak gerekirse birçok noktasında olduğu gibi .Net Framework üzerinde Socket uygulamaları geliştirmekte eskiye nazaran çok daha az efor sarfedilerek gerçekleştirilebilmektedir. System.Net.Sockets NameSpace’ i içerisindeki sınıfları doğru yer ve doğru kombinasyonlar üzerinden kullanarak uygulama geliştiriciler .Net Framework üzerinde çok optimize ve sağlam Socket uygulamaları geliştirebilmektedirler.

Peki .Net Framework üzerindeki bu esnek yapıya .Net Compact Framework üzerinde hangi oranda sahip olabilmekteyiz ? Mobil Cihazlar üzerinde Socket uygulamaları geliştirmek günümüzde hala bir ütopyamıdır ?

İşin biraz derinine inildiğinde özellikle 2.0 sürümü ile birlikte .Net Compact Framework kendisine hayranlık bırakabilecek seviyede başarılı ; konumuz ile ilişkilendirdiğimizde ise hayli sağlam bir grafik çizmektedir.

Socket uygulamaların geliştirilmesi bakımından neredeyse .Net Framework ile başabaş giden .Net Compact Framework , .Net Framework üzerinde olduğu gibi işletim sistemi üzerinde tanımlı olan API Fonksiyonlarını kullanan managed metotları uygulama geliştiricilerin kullanımına sunmaktadır.

Bu makalemizde ise sayfalar dolusu teori ile konuyu anlatmak yerine, Masaüstü Bilgisayarımız üzerinde çalışacak olan bir sunucu uygulaması  ile Mobil Cihaz üzerinde çalışacak olan bir istemci uygulamasını baz alan ; Socket’ ler üzerinden birbirleriyle haberleşen bir mobil chat uygulaması geliştireceğiz.

Bu noktada üzerinde çalışacak olduğumuz kavramlardan bahsetmeden herşeyin “neredeyse .Net Framework ile birebir aynı” olduğunu belirtmek daha doğru olacaktır.

Ayrıca uygulamanın geliştirilme aşamasında standart seviyede Socket kavramlarını biliyor olduğunuzu kabul edeceğiz.

Fakat her ne olursa olsun uygulamamızın parçalarını geliştirmeye başlamadan önce her iki platform üzerinde de ; .Net Framework ve .Net Compact Framework üzerinde de neredeyse birebir aynı çalışma mekanizmasına sahip Socket sınıfını ve metotlarını yüzeysel olarak incelemek bu noktada daha doğru olacaktır.

Sizlerinde bildiği üzere Socket ; bir uygulamanın dış dünya ile iletişim kurabileceği bir kapı olarak kafamızda rahatlıkla canlandırılabilir. Bu noktada kapının bir adresinin ; tipinin ve o kapıdan nelerin geçebileceğinin bilgisinin belirlenmiş olması kapının dış dünya üzerinde çalıştırılabilmesi açısından yeterli parametreler olabilmektedir.

Uygulama geliştiriciler Socket’ ler yardımıyla onlarca protokolün onlarca tipi üzerinden farklı uygulamalar ile haberleşebilir ; veri transferleri gerçekleştirebilirler. Bugün işletim sistemimiz üzerinde kullanıyor olduğumuz birçok “internet” bazlı uygulama işletim sistemimiz üzerinde tanımlı olan WinSock Fonksiyonları üzerinden socket kullanımını gerçekleştirmekte ; bizleri dış dünyaya bağlamaktadırlar.

Olaya bu açıdan bakıldığında Socket programlamanın hiçbir zaman kolay olmadığından ;ileri bir programcılık bilgisi ve araştırma gerektiğinden yazımızın başında bahsetmiştik.

Fakat .Net Framework’ e bakıldığında ise bu işin Managed sınıflar üzerinden ne kadar kolay gerçekleştirilebildiğinden yazımızın başında bahsetmiştik.

.Net Framework içerisinde bulunan System.Net.Sockets NameSpace’ i içerisinde bulunan Socket sınıfı bu noktada gerekli tüm altyapıyı biz Managed uygulama geliştiricilere sunmaktadır. Yapılması gereken tek şey gerekli parametreleri belirledikten sonra bu sınıfın üretilen instance’ ı üzerinden ilgili metotları çağırmak ve veri transferlerini gerçekleştirmek olacaktır.

Şu an ki amacımız bu sınıfı .Net Framework üzerinde kısaca tanıttıktan sonra senaryomuzun ilk parçasını ; masaüstü sunucu uygulamamızı geliştirmek ve hemen akabinde herşeyin ama herşeyin %95 oranında .Net Compact Framework üzerinde de aynı olduğunu ifade ederek makalemizin ilk bölümünü tamamlayacağız.

Socket sınıfı ile ilgili Teorik amaçlı anlatıma geçmeden önce bu noktada örnek uygulamamızın ilk adımını gerçekleştirmeye başlamak daha doğru olacaktır.

Amacımız Mobil Cihaz üzerinden bağlanabileceğimiz ; TCP Protokolü kullanılarak oluşturulmuş bir Windows Masaüstü Sunucu uygulaması geliştirmek olacaktır.

Bu amaca uygun olarak Standart bir C# Windows Application projesi açarak işe başlıyoruz.

Bir sonraki adımda şekildeki Windows Formunu tasarlıyoruz.

Amacımız basit bir arayüz üzerinden “Start Server” button’ u üzerinden dinleme durumuna geçen sunucu uygulaması ile Mobil Cihaz uygulamamızı haberleştirebilmek. Bunun için basit bir kaç kontrolü form üzerine ekliyoruz. Orda noktadaki kontrol bir ListBox kontrolüdür.

Sıra geldi kodlar üzerinde çalışacağımız noktaya. 

İlk olarak belirtmemiz gereken nokta şu olmalıdır ki  uygulamamız asenkron mimari üzerinden geliştirilmelidir. Aksi takdirde bağlantı gerçekleştirilmesi safhasından itibaren her mesaj beklendiği süreçte uygulama ekranı kitli kalacak ; uygulama herhangi bir işe yaramayacaktır.

Bu noktada Socket sınıfı üzerinden hazır gelen bazı asenkron metotları kullanarak bu mimariyi oturtacağız.

Hızlı bir şekilde kaldığımız yerden devam edelim. Kod tarafına geçtiğimizde temel olarak basit birkaç “Callback” metodu ve birkaç delege yardımı ile Socket nesnemizi oluşturup ; sunucu üzerinden “Listen” moduna geçireceğiz. Bundan sonraki adımlarda yapılacak olan tek şey mobil cihaz üzerinden bağlantıyı kurup mesajlaşmaya başlamak olacaktır.

İlk olarak bazı nesne referanslarını global scope alanı içerisinde tanımlıyoruz.

Dikkat edilecek olursa listenin en tepesine System.Net.Sockets NameSpace’ i içerisinde bulunan Socket sınıfının bir referansı tanımlanmış ; bir altına bağlantı kurulduğu noktada karşı istemciyi temsil edecek olan Socket’ in referansı ; onun altına ise Socket sınıfının asenkron metotları çalışmayı tamamladıklarında gidip haber verecekleri metotların adresini barındırabilecek bir signature’ a sahip ; AsyncCallBack delegesinin bir referansı tanımlanmıştır.

En alta ise karşı istemciden mesaj geldiğinde mesajın içerisine yükleneceği 1MB’ lık bir alan teşkil eden bir Byte[] tanımladık.

Kaldığımız yerden devam edelim.

Uygulama tasarımımız asenkron mimari üzerine geliştirileceğinden belirli eylemler “asenkron” olarak gerçekleştirildiğinde işlemlerin sonucu işleyebilmek ve uygulamanın yaşam sürecine devam edebilmesi adına bazı görevleri yerine getirebilmek için iki adet CallBack metodu tanımlıyoruz.

Hiç vakit kaybetmeden şekildeki kod bloğu ile ilgili gerekli açıklamaları ifade edelim.

Kolayca anlaşılabileceği üzere CallBack metotlarının kod sayfası içerisinde yerleştirilebilmesi için tanımlanmış Callback Methods isimli Region içerisine iki adet metot tanımlanmıştır. Bu metotlardan kırmızı kutu ile ifade edilen AcceptedCallBack metodu sunucuya Mobil Cihazımız üzerinden herhangi bir bağlantı başarılı bir şekilde gerçekleştirildiğinde çalıştırılmakta ; Socket objesinin EndAccept isimli Asenkron “sonlandırma” metodu üzerinden karşı socket’ i refere eden socket objesi alınmaktadır. Bir sonraki adımda ise RemoteSocket ismiyle alınan bu socket objesinin Asenkron mimari üzerinden BeginAccept metodu çağırılmakta ; kısaca karşı Mobil Cihaz üzerinden mesajlar “uygulamayı kitlemeden” beklenmeye başlamaktadır.

Bir alttaki, turuncu kutu ile ifade edilen metotta ise BeginReceive ile başlatılan bekleme süreci sonlandığında ; yani Mobil Cihazımız üzerinden bir mesaj geldiğinde çalıştırılacak olan kod blokları geliştirilmiştir.

İlk olarak dikkat edilecek olan satır gelen mesajın nasıl liste kutusu içerisine eklendiğidir.

Bir önceki metotta belirtildiği üzere gelen byte dizisi MessageBuffer isimli byte dizisi içerisinde tutulacaktır. Bu noktada System.Text.Encoding.GetEncoding(1254).Getstring metodu üzerinden faydalanarak gelen byte dizisini “türkçe karakter setine uygun olarak” metne dönüştürüp liste kutusu içerisine ekliyoruz.

Bu satırdan sonra yazdığımız satırda ise MessageBuffer dizisini “yeni gelecek olan” mesajlar için temizliyoruz ; ve uygulamamızı “mesajların gelebilmesi” adına tekrar “mesaj bekleme” moduna geçiriyoruz.

İşte en önemli kısımları halletmiş olduk. Sıra geldi uygulamamızı çalıştıracak olan Socket tanımlama ve mesaj gönderme işlemlerinin gerçekleştirildiği kod bloklarını geliştirmeye.

Amacımız sistemimiz üzerinde 15423 numaralı TCP portu üzerinden dinlemeye ve mesaj göndermeye yarayan bir socket tanımlamak olacaktır. Hiç vakit kaybetmeden şekilde kod bloklarını geliştiriyoruz.

Kod bloğunu ayrıntılı olarak incelediğimizde uygulamamız açıldığında sistem üzerinde TCP protokolü 15423 numaralı porttan dinleyecek ve Stream ; yani akış işlemlerinin gerçekleştirilebileceği bir Socket objesi tanımlanmaktadır. Bir sonraki satırda ise bu socket objesi sistemimiz üzerindeki fiziksel bir port ile ilişkilendirilmektetir. Ayrıca uygulama ekranı yüklendiğinde delegemizin objesi tanımlanmakta ; son olarak ise Asenkron işlemlerde daha önceki makalelerimizde bahsettiğimiz “bir objeye o’ nun oluşturulduğu thread dışında farklı bir thread üzerinden erişmeye çalıştığımızda yaşanan CrossThreadOperationException hatasına karşı” Control.CheckForIllegalCrossThreadCalls static değişkenine “sorun çıkarmaması adına” false değerini veriyoruz.

Button1 isimli Start Server button’ una bastığımızda ise tanımlanan socket objemizi Listen metodumuz üzerinden dinleme moduna geçiriyoruz. Ve BeginAccept metodu üzerinden asenkron mimariyi kullanarak uzaktan gelecek olan bağlantıları kabul edebilecek şekilde yapılandırıyoruz.

Son olarak btnSEND isimli button’ umuza tıkladığımızda ise yazılan metin System.Text.Encoding.GetEncoding(1254).GetBytes metodu üzerinden byte dizisine çevirmekte ve “eğer bağlı bir socket var ise” yani RemoteSocket referansı “null” değil ise karşı noktaya yani mobil cihazımıza göndermektedir.

İşte bu kadar !

Makalemizin ilk bölümünün sonuna geldik. Bir sonraki makalemizde bu makalede geliştirdiğimiz sunucu ile haberleşecek bir mobil cihaz uygulaması geliştireceğiz.


Ekin ÖZÇİÇEKÇİLER
Microsoft Certified Trainer
ekin.ozcicekciler@bilgeadam.com
MCP, MCAD.NET, MCSD.NET, MCSD.NET, MCTS, MCPD Ent.