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.