C++ Üzerinde Soket Programlama

 
typedef struct fd_set {
  u_int  fd_count;
  SOCKET fd_array[FD_SETSIZE];
}fd_set;

Gördüğünüz gibi içerisinde bir sayac ve bir de soket dizisi var. Biz dosya tanımlayıcı kümesine veri ekleyip çıkardığımızda aslında bu soket dizisine soket ekleyip çıkarmış oluyoruz ve sayac da ona göre güncelleniyor…

Hemen bir dosya tanımlayıcı kümesi tanımlayalım…

fd_set okunanlar;

Evet, artık okunanlar adında bir dosya tanımlayıcı kümemiz var, şimdi bunun içine soketlerimizi yerleştirmesi kaldı. İstediğimiz soketleri yerleştirip select fonksiyonunun 2. parametresine yani readfds ye yerleştirirsek, bu soketlerden birine veri geldiğinde select bizi uyarır ve biz de recv ile gelen veriyi alırız..  Sanırım taşlar yerine oturmaya başladı J

Şimdi tanımlayıcı kümemize nasıl soket ekleyip sileceğimizi öğrenelim. Bunlar için bazı makroları kullanacağız..

FD_SET(int fd, fd_set * okunanlar);  Bu makro ile kümemize bir soket ekleriz.

FD_CLR(int fd, fd_set * okunanlar);  Bu makro ile kümemizden bir soket siler   iz

FD_ZERO(fd_set *okunanlar);          Bu makro ile tüm kümeyi sıfırlayabiliriz.

FD_ISSET(int fd, fd_set * okunanlar); Bu makro ile soketi  kümemizde mi diye

Kontrol ederiz…                                                                                                

Burada ilk parametre olan int fd (file descriptor), dosya tanımlayıcısıdır, biz soketimizi yazacağız doğal olarak. Dikkat edilmesi gereken, diğer parametre dosya tanımlayıcı kümemizin kendisi değil adresi. Yani biz kümemizi parametre olarak geçerken & işlecini kullanmalıyız…

FD_SET(skt, &okunanlar);

FD_CLR(skt, &okunanlar); 

FD_ZERO(&okunanlar);  

FD_ISSET(skt, &okunanlar);

Şeklinde kullanacağız… Artık soket programlama ile ilgili birçok şeyi biliyoruz, uzman sayılmasak da rahatlıkla piyasadaki birçok programın biraz daha amatörünü yazabiliriz.

Sanırım artık bir örnek vermenin zamanı geldi.. İlk programımız bir chat sunucusu olsun..

********************************************************************

// Yazan: KuLTigiN

// www.tahribat.com

#include

#include

#define PORT 5000

int main(){

   WSADATA  wsdata;            // gereksiz MS işleri..

   SOCKET   ss,is;             // sunucu soket ve istemci soket

   fd_set   anatanim,gecici;    // ana ve geçici dosya tanimlayici kümeleri

   char     tmp[256];          // istemci verisi için tampon

   int      gelenbayt,boyut;   // recv de gelen veri, accept için boyut...

   int      i, j;              // döngü sayacları.

   struct sockaddr_in sunucu;  // sunucu adres bilgileri

   struct sockaddr_in istemci; //istemci adres bilgileri

 sunucu.sin_family = AF_INET;

 sunucu.sin_port = htons(PORT);

 sunucu.sin_addr.s_addr = INADDR_ANY;

 WSAStartup(MAKEWORD(2,0),&wsdata);

 FD_ZERO(&anatanim); // ana kümeyi ve gecici kümeyi temizle

 FD_ZERO(&gecici);     

//----------------------------- 

  if( (ss=socket(AF_INET, SOCK_STREAM, 0))==-1 )

       fprintf(stderr,"Sunucu soket hatasi!\n");

//----------------------------- 

  if( (bind(ss, (struct sockaddr *)&sunucu,sizeof(struct sockaddr) ))==-1 )

      fprintf(stderr,"Bind fonksiyonu yurutulemedi!\n");

//-----------------------------

  if (listen(ss,10) == -1)

     fprintf(stderr,"Port dinlenemiyor!\n");

//-----------------------------

 FD_SET(ss, &anatanim);

   for(;;) {                   // Ana for döngüsü

      gecici = anatanim;

if(select(0, &gecici, NULL, NULL, NULL)==-1)

fprintf(stderr,"select fonksiyonu yurutulemedi\n");

            i=gecici.fd_array[0];

//----------------------------------------------              

            if (i == ss) {

               boyut = sizeof(istemci); 

               is = accept(ss, (struct sockaddr *)&istemci,&boyut);           

                  FD_SET(is, &anatanim);             // ana listeye ekle

  printf("Istemci baglandi: %s\n",inet_ntoa(istemci.sin_addr));

                  

//----------------------------------------------                 

             else {                   

                   if ((gelenbayt=recv(i, tmp, sizeof(tmp), 0)) <= 0) {

                      if(gelenbayt==0)  fprintf(stderr,"Baglantikoptu \n"); 

                          else      fprintf(stderr,"Baglanti hatasi \n");                                

closesocket(i);

                        FD_CLR(i, &anatanim);

                        }

//----------------------------------------------                        

                   else    

   for(j = 0; j < anatanim.fd_count; j++)                              if(anatanim.fd_array[j] != ss && anatanim.fd_array[j] != i)

         send( anatanim.fd_array[j], tmp, gelenbayt, 0);                              

//----------------------------------------------                   

                }

    }

WSACleanup();                 

return 0;

}

//Bitti :)

Tarih:
Hit: 10334
Yazar: Tugberk



Yorumlar


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