Socket Programlama Bölüm -2

Ebru Aksoylu —  29 Aralık 2014 — 6 Comments

Önceki yazımızda cihazların nasıl iletişim kurduğu ve iletişim kurallarından kısaca bahsetmiştik. Şimdi ise “Port Dinleyici” adını verdiğimiz sunucu programını yazmaya başlayacağız.
Her cihazın yönlendirildiği porta bıraktığı sinyalin formatı farklıdır. Bu sinyallerin formatının üreticiden üreticiye değiştiğine değinmiştik. Sinyaller genellikle String dizisi halinde gönderilir. Ve dizi içerisindeki değerler birbirinden ayraçlar ile ayrılır.
Duman dedektörümüzün sunucuya gönderiği sinyalin aşağıdaki dizi olduğunu varsayalım.

Örnek Sinyal: 
1234;1200;28032014;28.4;300;0;0;0;1100;300;50;25 
Parçalanmış Hali  
1234= Cihaz Tanımlayıcısı 
1200 = Saat 
28032014 = Tarih (GünAyYıl) 
28.4= Sıcaklık 
300= Basınç (Bar) 
0 = Dedektör Açık/Kapalı(1/0) 
0 = Enerji Var/Yok(1/0) 
0 = SD Kart Takılı/Takılı Değil (1/0) 
1100 = Basınç Set Değeri (Yüksek) 
300 = Basınç Set Değeri (Düşük) 
50=Sıcaklık Set değeri (Yüksek) 
25 =Sıcaklık Set değeri (Düşük) 

; = Parçalama Ayıracı

Bu uzun string dizisini ( sinyali ) Parçaladıktan sonra geriye değerleri kullanmak kalıyor. İşin programlama ile ilgili olan kısmına yavaş yavaş geçelim…

Eski nesil socket programcıları ( en azından benim tanıdıklarım ) hala Delphi ‘nin dinleyici yazarken daha kullanışlı fonksiyonlara sahip olduğunu ve pratikliğini savunurken, ben C# ‘ın multithreading konusunda daha başarılı olduğunu düşünüyorum. Özellikle UDP port kanalını kullanan cihazlar için Threading çok önemli. Çünkü aynı anda sırasız ve düzensiz olarak gelen verilerin kaybolmaması için çok kanallı işlem yapabilme yeteneğine sahip bir dinleyici programlamamız gerekiyor.

Gelelim programımızı oluşturmaya…

Öncelikle Boş bir Windows Form Application açarak Form oluşturalım. Sinyal Trafiğini başlatmak ve bitirmek için 2 adet buton(kodlarda btnStart ve btnStop olarak kullanacağız) ve 1 adet Richtextbox nesnesi bizim için arayüzde yeterli olacak. Oluşturduğumuz projenin isim uzaylarını tanımladığımız kısmına :

using System.Net;
using System.Net.Sockets;using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Data.SqlClient;

Kütüphanelerini eklememiz gerekiyor. IO.Ports kütüphanesini port giriş çıkış işlemleri için , Net kütüphanesini Socket nesnelerini yaratmak için , Threading kütüphanesini çok kanallı işlem yapabilmek ve son olarak Data.SqlClient kütüphanesini de SQL veritabanıyla işlem yapabilmek için kullanacağız.

 

Yazacağımız fonksiyonlarda kullanmak üzere Global olarak UdpClient, Thread ve IpEndPoint sınıfından nesneler oluşturacağız.

public UdpClient rcv;
public Thread threadreceive;
public IPEndPoint remoteend = new IPEndPoint(IPAddress.Any, 0);

Öncelikle Sinyal Trafiğini Başlatacak Butonumuzun “Click” olayına çok kanallı bir Threading başlatacak komutu verelim.

private void btnStart_Click(object sender, EventArgs e)
{
    btnStart.Enabled = false;
    rcv = new UdpClient(8001);
    Initialize();
}

Initialize fonksiyonunu Thread işlemimiz için ayrıca yazıyoruz.

public void Initialize()
{
    threadreceive = new Thread(recievemessages);
    threadreceive.Start();
}

ReceiveMessages isimli bir fonksiyon oluşturarak buradan UDP porta gelen sinyalleri ayrıştıracağız. Byte tipinde gelen veriyi görebilmek için GetString Metodu ile string olarak alıp Richtextbox’a yazdırıyoruz.

public void recievemessages()
{
    char [] gelenverichar ;
    Byte[] rbytes = rcv.Receive(ref remoteend);
    BitArray bt = new BitArray(rbytes);
    string dt = System.Text.Encoding.Unicode.GetString(rbytes);
    gelenverichar = Encoding.ASCII.GetChars(rbytes);
    string s = new string(gelenverichar);
    Appendtextbox(s);
}

Richtextbox’a verileri yazdırmak için Appendtextbox metodunu oluşturuyoruz.

public void Appendtextbox(string deger)
{
    if (richTextBox1.InvokeRequired==true)
    {
        this.Invoke(new Action<string>(Appendtextbox), new object[] { deger });
        return;
    }

    richTextBox1.AppendText("Signal Date: "+DateTime.Now.ToString()+" "+deger+Environment.NewLine+Environment.NewLine);
    parcalayaz(deger);
    Initialize();
}

Verileri Parçalayarak oluşturduğumuz veritabanına değerleri yazmaya başlayalım…

Bu aşamadan önce verilerinizi kaydedebileceğiniz bir veritabanı oluşturun ve Trafik isminde bir tablo ekleyin. Tabloda dedektörümüzün algıladığı anlık değerleri göstermeniz yeterli olacaktır.Örneğimiz için Kayitid ,Cihazid , Saat , Tarih , Sicaklik , Basinc sütunlarını oluşturmalısınız.

Sinyali Parçalayacak fonksiyonun açıklamalarını anlaşılır olması için satır aralarında yapacağım.

public void parcalayaz(string parcalanacakdeger)
{
    //Split metoduyla (;) karakterini ayraç kabul ederek parçalatıp degerler isimli    string diziye atıyoruz.
    string[] degerler = parcalanacakdeger.Split(';');
    // Veritabanı bağlantısını sağlıyoruz.
    SqlConnection connlog = new    SqlConnection(@"DataSource=85.205.12.75;Initial Catalog=DumanDedektor;User ID=sa;Password=dinleyiciyaziyoruz");
    //degerler dizisindeki elemanları ait oldukları değişkenlere atıyoruz.
    string cihazid = degerler[0].ToString();
    string saat = degerler[1].ToString();
    string tarih = degerler[2].ToString();
    string Sicaklik = degerler[3].ToString();
    string Basinc = degerler[4].ToString();
    //oluşturduğumuz veri tabanı bağlantısını açıyoruz.
    connlog.Open();
    //Sqlcommand nesnesinden CmdKaydet isimli bir nesne türetip insert sorgumuzu    yazıyoruz.
    SqlCommand CmdKaydet = new SqlCommand(@"INSERT INTOTrafik(Cihazid, Saat,Tarih,Sicaklik,Basinc) VALUES('" +cihazid + "', '" +saat + "', '" +tarih + "', '" + Sicaklik+ "', '" + Basinc+ "')",     connlog);
    //Oluşturduğumuz insert sorgusunu parse ediyoruz.
    CmdKaydet.ExecuteNonQuery();
    //Bağlantımızı kapatıyoruz.
    connlog.Close();
}

Sinyali Parçalayıp Veritabanına yazdığımıza göre artık Trafiği sonlandırabilmemizi sağlayacak Thread Sonlandırma butonunu oluşturabiliriz.

private void btnSTOP_Click(object sender, EventArgs e)
{
   threadreceive.Abort();
   btnStart.Enabled = true;
}

Böylece UDP portuna veri yazan bir cihazın sinyal dinleyicisini hazırlamış olduk.

3. Bölümde TCP porta veri gönderen ,ve cevap alan bir Sunucu-Client programı yazacağız. Yeni makalemizde görüşmek üzere…

Ebru Aksoylu

Posts

Bilgisayar bilimleri tutkunu ve malulen emekli voleybol oyuncusu.

6 responses to Socket Programlama Bölüm -2

  1. Yazının 2 nci bölümü beklediğimden hızlı geldi. Kendi adıma teşekkür ederim. Gelen verileri RichTextBox nesnesine yazdırdıktan sonra, nesne içerisindeki verileri silmemiz gerekiyor mu? Yoksa verilerin kalmasının herhangi bir sakıncası yok mu? Geniş çaplı işletmeler için (gelen veri yoğunluğu açısından) verimli olabilir mi?

  2. Richtextbox nesnesine yazılan veriler 10 yada 20 satırı geçtikçe sildirebilirsiniz. Sinyalleri Richtextbox’a yazdırmak sadece dinleyiciye görsellik katar ve verinin gelip gelmediğine dair fikir edinmemizi sağlar. Fakat bunları Thread içinde kontrol ettirip ara ara temizletmeniz RAM belleğinizin şişmesini engeller.

  3. Öncelikle Türkçe yazılım kaynaklarının sıkıntılı derecede kötü ve az olduğu şu zamanlarda düzenli ve net bir anlatım görmüş olmak “Yazılıma kadın eli değdi.” dedirtti bana sonunda. Teşekkürler çok işime yaradı.Kolay gelsin.

  4. İbrahim Adam 21 Haziran 2015 at 12:01

    iyi günler ebru hanım;
    benim buna benzer bir sorunum var yardımcı olacağınızı düşünüyorum, bitirme projem için c# ortamında bir arayüz tasarlandı ve cihazımıza bir adet tetik mesajı geldiği zaman verileri göndermeye başlıyor bu işlemi seri port ile yapabliyoruz fakat bizi udp ile de lazım sahsınıza mail atsam yardımcı olabilir misiniz ?

  5. Kamil ÜNLÜ 25 Mart 2016 at 15:11

    Devamı yokmu ?

  6. databesede sinyalleri işlerken, udpden aldıgımız sınyallerı mı kullanıyoruz database bağlantısıyla detektörden mi alıyoruz sinyalleri

İbrahim Adam için bir cevap yazın Cevabı iptal et