C++ Üzerinde Soket Programlama

Kısaca özetlersek…

Sunucu                                              İstemci

*Bind ile soketi hazırlarız…                        *bu arada bir şey yapmayız..

*Listen ile soketi dinleriz…                        *connect ile bağlantı isteği yollarız..

*Accept ile isteği kabul ederiz                   *istediğimiz gibi veri alışverişi yapabiliriz artık

Sonunda sunucumuzla istemcimizi birbirine bağladığımıza göre artık veri alışverişine geçebiliriz…

Çok basit iki fonksiyon ile her türlü veri alışverişini gerçekleştireceğiz. İnternetten dosya indirirken, web sitesi gezerken, telnet ile ftp ye vs bağlanırken aslında hep bu fonksiyonlar çalışır arka planda. Ve gerçekten basit fonksiyonlardır.

Send ve recv fonksiyonları..

Send fonksiyonu adi üstünde veri yollamak için, recv fonksiyonu ise veri almak için kullanılır. Bu fonksiyonlara geçmeden önce unuttuğum birşeyi ekleyeyim, bu kullandığımız fonksiyonların tamamı hata durumunda -1 değerini geri döndürür. Bu yüzden her aşamada hata kontrolü yapmayı ihmal etmeyelim. Başlarda zor gelir ancak zamanla programlamanın en önemli kurallarından birisi olduğunu anlarsınız..

send(skt,tmp,sizeof(tmp),0);

Evet bu basit fonksiyon tüm web iletişiminin kalbidir adeta J skt bağlantı kurduğumuz soket, tmp yollayacağımız verilerin bulunduğu adres, sizeof(tmp) kaç bayt veri yollayacağımız , son parametre tcp/ip de herzaman 0 olarak bırakılmalı.

Send fonksiyonu gönderdiği bayt miktarını döndürür. Neden böyle bir değer döndürdüğünü düşünebilirsiniz, sonucta göndereceği değeri zaten 3. parametrede belirtiyoruz..

Maalesef send fonksiyonu sizin ona gönder dediğiniz verinin tamamını göndermeyi garanti etmez. Bir bayt bile gönderse başarılı olarak döner ve 1 değerini döndürür.

Eğer bir hata olursa tahmin edeceğiniz gibi -1 değerini döndürür.

Hemen umutsuzluğa kapılmaya gerek yok J çok basit bir fonksiyon yazarak istediğimiz tüm verinin ne pahasına olursa olsun gitmesini sağlayabiliriz. Böylesi çok daha güvenlidir.

Recv fonksiyonuna gelecek olursak ..

recv(s2,tmp,sizeof(tmp),0);

send fonksiyonunun aynısıdır, parametrelerin anlamı da aynıdır, yani send ile tmp deki veri yollanır recv ile gelen veri tmp alanına yazılır. Recv fonksiyonunu çalıştırdıktan sonra fonksiyon veri gelene kadar bekler. Aslında recv fonksiyonu blokeli ya da blokesiz modda çalışabilir.

Yani istersek veri gelene kadar bekleme o anda ağ tamponunda veri varsa al yoksa boşver sonraki komuta geç diyebiliriz.

Ancak varsayılan olarak blokeli moddadır ve herhangi bir veri gelene kadar bekler. Geri dönüş değeri olarak aldığı bayt miktarını döndürür, o an ağ tamponunda 1 bayt bile olsa bu bir baytı okuyup başarılı bir şekilde dönüş yapar.

Eğer hata olursa -1 değerini döndürür. Ama bu fonksiyona has olan bir değer daha vardır. Eğer karşı taraf ile bağlantı kopmuşsa recv fonksiyonu 0 değerini döndürür. 

Bu bloklama olayı sadece recv fonksiyonuna özgü değildir. Ağ programlama da karşı bilgisayardan her an bilgi alamayacağınız için ve bağlantı her an düzgün işlemeyebileceği için bloklama önemlidir. Mesela accept fonksiyonu da blokelidir. Eğer accept fonksiyonunu çağrırsanız bir bağlantı gelene kadar bekler. Bir bağlantı isteği gelince yeni bir sokete bağlantıyı atar ve sonraki satırdan devam eder.

UDP hakkında da bir şeyler anlatayım. Udp de sunucu ile istemcinin bağlantı kurmasına gerek yoktur. Verinin iletilip iletilmediği ile de ilgilenilmez. program verinin teppesine adresi portu yapıştırır yollar, diğer program da bu veriyi alır kullanır.

Ortada bir bağlantı olmadığına göre connect fonksiyonuna da gerek yoktur. Udp ile veri gönderme ve veri alma fonksiyonları tcp ye çok bezner ama ufak tefek farklılıkları vardır. Veri göndermek için sendto veri almak için ise recvfrom fonksiyonları kullanılır.

Hatırlarsanız tcp soketleri için her soket ancak bir bağlantı için kullanılır demiştik. Yani siz bir soketle bir sunucuya ya da istemciye bağlandıysanız o soket artık sadece o bağlantıya özgüdür. Dolayısıyla send fonksiyonu ile soketten  bir veri yolladığınızda bu verinin nereye gideceği bellidir.

Ancak udp soketleri bağımsızdır. Tek bir soket birsürü farklı bilgisayara veri yollayabilir. Ortada bağlantı yoktur.

Eğer bir soketi sadece yarattıysak ve hiçbir adres, port bilgisi ile bind etmediysek o halde veri yollarken hangi ip ve porta yollayacağını da parametre olarak bildirmeliyiz..

sendto(skt,tmp,sizeof(tmp),0,(struct sockaddr*)&bilgiler \

,sizeof(struct sockaddr) );

Sanırım tanıdık gelmiştir. İlk üç parametre send ile tamamen aynı, 4. parametre hangi ip ve porta gönderileceği bilgisini tutar, son parametre ise bilgiler yapısının boyutunu tutar.

Recvfrom fonksiyonu da çok benzerdir.

recvfrom(skt,tmp,sizeof(tmp),0,(struct sockaddr*)&bilgiler \

,sizeof(struct sockaddr) );

Bu fonksiyon da kendisine gelen veriyi tmp ye yazar. Udp de aslında bir bağlantı ve konrol sistemi olmadığı için veriler tcp den çok daha az paketlenir. Kendi yazacağınız bir uygulama katmanı ile udp paketlerini numaralandırarak sırayla alır ve aldığınız her veri için aldım cevabı gönderebilirsiniz. Aldım cevabı gelmezse aynı veriyi tekrar gönderirsiniz. Bu yöntem çok sık kullanılır. Kendi iletişim protokolünüzü yazmanız mümkün yani. Aslında udp daha çok ses ve görüntü iletiminde kullanılır. Çünkü canlı ses ve görüntü iletiminde tcp ile verinin paketlenmesi boyutunu çok büyüteceği için o ses ve görüntü anlık olmaz. Ses ve görüntü iletiminde paket kontrolü yapmak da genelde tercih edilmez, buna rağmen sorunsuz çalışır…

Tarih:
Hit: 10590
Yazar: Tugberk



Yorumlar


Siftahı yapan siz olun
Yorum yapabilmek için üye girişi yapmalısınız.