|  | 
        
            | 
                    
                        | C# ile Network Programlama-2 |  |  
                        | 
	
    
		
            | Gönderiliyor lütfen bekleyin... | 
 |  | 
        
            | Merhabalar, Network programlama yazı 
dizisinin ikincisine başlamadan önce konunun daha anlaşılır olması için birinci 
yazıyı okumanızı tavsiye edirim. 
		Network’de yani haberleşmede ne nasıl oluyor bunların mantığını, nasıl 
		çalıştığını, protocollerin nasıl ve hangi safhalarda işlediğini bilmeden 
		network yazılımı geliştirmemiz zor olucaktır. Örneklerin kullanılabilirliği (internet 
çıkışları) açısından 
		uygulamaları Tcp protocolü üzerinden geliştirmeye çalıştım. Bu protocolün internet 
		uygulamalarında kullanıldığından bahsetmiştim. Birde OSI referans modeli 
		ile ne yaptığımızın özüne inelim.Aşağıda meşhur OSI modelinin yapısını 
görebilirsiniz. 
 
 
				
					| Application>>>>Şuanda 
                    bu katmanda çalışmaktayız. | Network 
                    yazılımı geliştirirken bu katman bizim kullandığımız 
                    katmandır. |  
					| Presentation | Application 
                    katmanının uzantıları, plug bilgilerinin tutulduğu 
                    katmandır. |  
					| Session | Veri 
                    girişlerinde gelen verilerin kaydedilmesinin sağlandığı 
                    katmandır. |  
					| Transport layer | Tcp-Udp 
                    protocollerininde kapsamı içinde olan katmandır. 
                    Applicationdan gelen datalar burada networkte yolculuğa 
                    çıkmak için hazırlanır. |  
					| Network | Network 
                    paketler arası haberleşme olarak litaratürde geçmektedir.Ama 
                    genelde ingilizce kavramları terimsel olarak kabul etmek 
                    daha mantıklı bu yüzden frame diyeceğiz. Yani yolculuğa 
                    frameler ile başlıyoruz.Aslında network tam bir yolculuk. 
                    Düşününki bir tren yolculuğuna çıkıcaksınız. Daha önceden 
                    nereye gideceğinizi biliyorsanız, hangi trenle gideceğinizi 
                    de bilirsiniz. İşte bizim yolculuğumuzda gideceğimiz 
                    yer(destination ip), gittiğimiz yol(kablolar), başlangıç 
                    adresimiz(source ip) olarak düşünülebilir. Aslında mantık 
                    düz olarak bu. Eğerki yolda tren raydan çıkmaz, vagonları 
                    patlamaz ise hedefe ulaşabiliriz. Yolda kaza olursa bu 
                    kazalara "collision" denir. Bir kaza olduysa frameler 
                    patlar. |  
					| Data Link | Bu katmanda ip 
                    header’lar ve frame trailer denilen yapılar transport 
                    layerde ayrılan framelere eklenir. |  
					| Physical | Tamamen 
                    bitlerin iletildiği kablolar ve sinyallerin dolu olduğu 
                    katmandır. |  Haberleşmenin Sağlanması:
Haberleşme sürekli olarak birbirine haber gönderme mantıyla çalışır. Yani bir 
akarsu yapısının bire bir aynısıdır diyebiliriz. Bir akarsu sürekli akar. 
İnsanların çok olduğu yerde akarsunun şiddeti azalır az olduğu yerde ise hızı 
artar. Gelelim konumuza; bizim akarsuyumuzda frameler sürekli akar. Yani sürekli 
akan bu akarsuda bazı bilgileri balık gibi tutmak istersek akarsuyun tamamına 
bir ağ koyarak bu balıkları tutabiliriz. Yani bir server uygulaması paketleri 
sonsuz ve bitmeyen bir döngü içinde dinleyecektir. Paketi gönderecek client’ ın 
ise böyle bir şeye ihtiyacı yoktur. Sonuçta client akarsuya bir kere frame 
bırakıyor o kadar. En az boyutlu, yani data içermeyen frame boyutu 64 byte’dır. 
Dolayısıyla data yüklendikçe akarsu yoğunluğu artacak ve server biraz 
yavaşlayacaktır.
 
 
  
 
 
 .Net’te network için kullanacağımız isim 
alanları ve class’lar:
 
 Kullanacağımız isim alanları 
        System.Net, System.Net.Sockets isim alanlarıdır. Bu ikisinin tüm 
        nesneleri networkle ilgilidir. Diğer kullanacağımız isim alanları  
        ise; System.Threading, System.Text isim alanları. Dilerseniz Network 
        programımıza geçelim. Bir server ve bir client olduğunu düşünelim. 
        Client mesaj yollayınca server bu mesajı aldığını karşı tarafada 
        yollasın. Yani bir nevi chat. Bunun için işe server’dan başlayalım.
 
 server.cs:
 
 Server baştada söylediğimiz gibi 
        sürekli dinleme durumunda olacak. Bu yüzden bu işi sonsuz bir döngü ile 
        hallederiz ama sonsuz döngü çalışınca uygulamamızın kilitlenmesine yol 
        açabilir. Bu yüzden sonsuz döngü olan metotu kanallamalıyız. Bu 
        kanallamayı threading namespace’i ile yapalım. Bu kanallama işeminin 
        uygulama başlar başlamaz olması en mantıklısı. Bu yüzden bu işlemi 
        Formun constructor’ında gerçekleştireceğiz.
 
 System.Threading
 
 
  Yeni bir kanal oluşturduktan sonra bu kanalı 
try-catch ile kırılmayı önlemek için kontrol etmek gerekiyor. Kanal.Priority 
bizim kanala verdiğimiz önceliktir. Kanal oluşturulurken, Thread class’ı ile 
yeni bir nesne yaratılırak dinlemeye alınıyor. Tabiki bizim dinle adlı void 
metotumuz sonsuz döngü........
    | using System.Threading;
    public Form1() {
 InitializeComponent();
 Thread kanal=new Thread(new ThreadStart(dinle));
 
 try
 {
 kanal.Start();
 kanal.Priority=ThreadPriority.Highest;
 MessageBox.Show("Server 
    açıldı");
 }
 catch(ThreadAbortException hata)
 {
 kanal.Abort();
 MessageBox.Show("Bekleyen 
    paket yok");
 }
 }
 |  
 Not:Threading işlemiyle daha önce ilgilenmeyen ve 
mantığını tam kavramayanlar Msdn’den yada daha önce sitede yayınlanan threading 
ile ilgili makalelere bakarak bilgilerini geliştirebilirler ki, geliştirmekte 
olduğumuz network uygulamalarının anlaşılması açısından bu kavramların iyi 
öğrenilmesi gereklidir..
 
 System.Text:
 
 
  
    | using System.Text; // bu namespace ile 
    text işlemlerini kolayca gerçekleştirebiliriz.Yazıyı byte dizisine,diziyi 
    yazıya çeviren bir yapı. byte[]dizi=Encoding.ASCII.GetBytes("CANER");//Kelimelerin ascii kodlamadaki 
    byte değerlerine alarak diziye yerleştirir.terside geçerlidir
 string veri=Encoding.ASCII.GetString(dizi);.//Aynı şekilde byte diziside 
    string veriye çevrilebilir.
 |  System.Net.Sockets:Bu isim alanında 
bulunan bir çok class ise bizim esas işlerimizi yapan metotları barındırıyor. Bu 
kavramlara server’ı dinleme işlemini yapan TcpListener ile başlayalım.
 
 
 
                  Yeri gelmişken port kavramını da açıklayalım. 
Portlar işletim sitemi, uygulamaların ve protocollerin ortak kullandıkları çıkış 
birimleridir. port sayısı 65000 civarındadır. 1023’e kadar olan portlar bilinen 
portlardır. Yani belirli protocoller için hizmet verirler. Örneğim http:(yani 
web) 80.porttan, ftp:21’den,telnet 23’den vs. Bunlar dünyada standart olarak 
kabul edilmiş numaralardır. Buradan şu çıkarki; iki bilgisayar konuşacaksa aynı 
port numarasını kullanmalıdır. Ben uygulamada 10000 numaralı portu bizim 
uygulamamız için ayırdım. Eğer bir firewall bilgisayarınızda kurulu ise bu 
portları kapamış olabilir. Bu yüzden firewall’dan 10000 numaralı portu açmasını 
ayarlayın yada firewall’u geçici olarak kapayın.
                    | TcpListener dinleyici=new 
                    TcpListener(port); dinleyici.Start();
 |  
 
 
  Görüldüğü gibi 
                        yukarıdaki örnekte sonsuz döngü ile 10000 numaralı port 
                        dinleniyor. Böylece bütün işlemler byte dizileri ile 
                        olucağı için Text kütüphanesinin metotları kullanılarak 
                        kolay biçimde dönüşüm sağlanıyor. Fakat bu dönüşümde 
                        Ascii karakterlerini kodladığımız için Türkçe 
                        karakterler doğal olarak çıkmayacak ve anlamsız 
                        karekterler oluşacaktır. İşte soket sınıfı tam anlamıyla 
                        TcpListener’ın türetildiği bir classtır ve bu class ile 
                        istenilen protocol’den soket oluşturulabiliriz. Biz 
                        burda dinlenen veriyi soket nesnesine bağlayarak soket 
                        ile networke veri yollama ve networkten veri okumayı 
                        yapabiliyoruz.TcpListener ise adındanda anlaşıldığı gibi 
                        portu dinlemeye alıyor. Burada bir dinleyip sonra 
                        porttan dinlemeyi kesiyoruz, fakat sonsuz defa bu işlemi 
                        gerçekleştirmemiz veri akışını sağlamış oluyor.
Ayrıca buttonlarlada threading kanalını askıya 
alarak verilerin sıra ile portta yığılması ve beklemesi sağlanıyor. Resume ile 
bu porttan veri akışı tekrar sağlanıyor. Thread’i askıya almak bizim sonsuz 
döngümüzün çalışmadığı anlamına gelmez. Sadece thread’e bir ara veriyor ve 
veriler bir kuyruk oluşturuyor.
							client.cs
    | const int port=10000; private void dinle()
 {
 string cevap="Mesajiniz basariyla 
    alinmistir.";
 string ip;
 string gelen;
 TcpListener dinleyici=new 
    TcpListener(port);
 byte[]gelenveri_dizi=new byte[1024];
 byte[]gonderveri_dizi=Encoding.ASCII.GetBytes(cevap);
 while(true)
 {
 dinleyici.Start();
 Socket 
    soket=dinleyici.AcceptSocket();
 soket.Receive(gelenveri_dizi,gelenveri_dizi.Length,0);
 gelen=Encoding.ASCII.GetString(gelenveri_dizi);
 listBox1.Items.Add(gelen);
 ip=soket.RemoteEndPoint.ToString();
 listBox2.Items.Add(ip);
 soket.Send(gonderveri_dizi,gonderveri_dizi.Length,0);
 label4.Text=listBox1.Items.Count.ToString();
 dinleyici.Stop();
 }
 }
 |  
 Gelelim client kısmına. Bu Kısımda 
kullanacağımız 2 tane class varki bunlar; TcpClient ve NetworkStream classları .
 
 Tcpclient:
 
 TcpClient  tam anlamıyla client için 
tasarlanmış bir yapıdır ve client’ın nereye veri göndereceği, nereye 
bağlanacağı, verileri nasıl paketleyeceği, nasıl ileteceğini belirlemede 
kullanılır.
 
 
 
  gonder isimli TcpClient nesnesi oluşturularak 
clientımız hazır duruma geçiyor ve böylece servera baglanıyor. Daha sonra ise 
Tcpclient nesnesinin metodlarından olan GetStream() ile bu baglantı 
NetworkStream nesne’sine atanıyor. NetworkStream nesnesi ise paketleme 
işlemimizi yapan nesne durumundadır. Dikkat ettiyseniz gonderilen mesaj byte 
dizisine çevrilmiştir. Aynı şekilde gelen verilerde ReceviBufferSize özelliğinin 
döndüğü değer olan gelen veri boyutu kadar bir dizi yaratılıyor. Artık sadece 
Yazma işlemimi Okuma işlemimi yapıyoruz buna karar vermemiz gerekiyor. Bunlar 
ise NetworkStream sınıfının ve üyelerinin işi.
    | TcpClient gonder=new TcpClient(ip,port); NetworkStream okuryazar=gonder.GetStream();
 string mesaj=textBox1.Text;
 byte[]mesaj_dizi=Encoding.ASCII.GetBytes(mesaj);
 byte[]gelen=new 
    byte[gonder.ReceiveBufferSize];
 |  
 NetworkStream:
NetworkStream class’ı bir stream classı’dır. Eğer 
daha önce dosyalama ile uğraştıysanız StreamWriter, StreamReader’ı hatırlarsanız 
ki mantık aynıdır. Sonuçta veri akışı bu Streamler ile yapılır.
 
 
  Burada networkstream nesnesi olan okuryazar 
class’ından CanRead ve CanWrite ile bool bir veri tipi döner. Eğer okuma varsa 
karşı taraf bize veri yolluyor anlamındadır. Biz bunu okuryazar nesnesinin read 
metotuyla bir byte dizisi içine alarak veriyi elde ederiz. Eğer yazma durumu 
varsa göndereceğimiz veriyi bir byte dizi içine alarak bu diziyi okuryazar 
nesnesinin Write() metotu ile yazarız. Eğer bu durumlar kabul edilmezse yani bir 
okuma-yazma durumu permit konumu doğru değilse Stream kapanarak else bloğundan 
çıkılarak kaldığı yerden devam eder. Birde okumamı önce yapılacak,yoksa yazmamı 
yapılacak burası önemlidir. Eğer okumayı önce yaparsak ilk başta servera gelen 
veri olmadığı için sonsuz döngüde takılıp kalacaktır. Bu yüzden ilk önce veriyi 
yazalımki cevabı alalım böylece bu sorun giderilir.
    | if(okuryazar.CanWrite) {
 okuryazar.Write(mesaj_dizi,0,mesaj_dizi.Length);
 }
 else
 {
 gonder.Close();
 return;
 }
 if(okuryazar.CanRead)
 {
 okuryazar.Read(gelen,0,(int)gonder.ReceiveBufferSize);
 string 
    gelenveri=Encoding.ASCII.GetString(gelen);
 listBox1.Items.Add(gelenveri);
 }
 else
 {
 gonder.Close();
 return;
 }
 |  
 
   
 
  
 Anlatımlar ile ilgili eleştirilerinizi belirtmeniz 
herkes için yararlı olacak ve hatalarımızı görmemize yardımcı olacaktır. C# ile 
Network programlama-3 yazısında görüşmek dileğiyle..
 
 NOT : İp adresini 127.0.0.1 yapmamızın 
sebebi loopback ile kendi bilgisayarımız üzerinde bir network gibi çalışmamızı 
sağlamasıdır. Bu ip adresini değiştirerek bilinen bir ip adresinden sizin 
servera internet’ten mesaj gönderilmesini sağlayabilirsiniz. Bununla birlikte 
server’ı ilk açtığınızda bir hata alacaksınız. Bu hatanın sebebi o anda bağlanan 
makina olmaması ve veri gelmemesidir. Devam ederseniz, clientlar masaj 
yolladıkça bu hata çözülecektir. Eğer internetle işim olmaz diyorsanız TcpClient 
nesnesi yerine UdpClient nesnesini kullanmanızı öneririm. TcpClient ile çalışma 
mantığı metotları benzer.
 
 Kaynak 
kodlar için tıklayın.
 
 CANER ŞAHAN
 [email protected]
 
 
 
                Makale:C# ile Network Programlama-2 C#, Visual C# ve .NET Caner Şahan
 | 
        
            |  | 
        
            |  | 
        
            | 
                    
                        
                            
                        
                            Eklenen Son 10 
                            Bu Konuda Geçmiş 10 
                        
                            Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
                         
                            Son Eklenen 10 Makale Yükleniyor
                         
                            Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
                         | 
        
            |  |