struct'lar ve Veri İle Uğraşmak
Önceki Beej'in Ağ Programlama Kılavuzu Sonraki
struct'lar ve Veri İle Uğraşmak
İçindekiler
1. Veri Türlerini Dönüştür!
2. IP Adresleri ve Bunlarla Uğraşma Yöntemleri
Hele şükür bu aşamaya gelebildik. Artık biraz programlamadan bahsedebiliriz. Bu bölümde soket arayüzleri tarafından kullanılan pek çok veri türünü ele alacağım çünkü bunlar gerçekten önemli.
Kolay olanlarla başlayalım: bir soket tanımlayıcı. Bir soket tanımlayıcı aşağıdaki türdendir:
int
Evet, gayet klasik, alışık olduğumuz basit bir int.
İşte bu aşamadan itibaren işler biraz garipleşmeye başlıyor bu yüzden de dikkatlice okuyun ve bana güvenin. İlk bilmeniz gereken: iki tür byte sıralaması vardır: en önemli baytın (ki buna bazen öktet de denir) önce geldiği sıralama veya en önemli baytın sonra geldiği sıralama. Bu sıralamalardan birincisine "Ağ Bayt Sıralaması" (Network Byte Order)[136] denir. Bazı makinalar içsel olarak veriyi kendi belleklerinde bu şekilde depolar, bazıları ise bu sırayı dikkate almaz. Bir şeyin Ağ Bayt Sıralaması'na göre sıralanması gerektiğini söylediğimde htons() gibi bir işlev çağırmanız gerekecek ("Konak Bayt Sıralaması"ndan [Host Byte Order] "Ağ Bayt Sıralaması"na dönüştürebilmek için). Eğer "Ağ Bayt Sıralaması"ndan bahsetmiyorsam o zaman ilgili veriyi olduğu gibi yani "Konak Bayt Sıralaması" düzeninde bırakmanız gerekir.
My First Struct™ -- struct sockaddr. Bu veri yapısı pek çok türde soket için soket adres bilgisini barındırır:
struct sockaddr {
    unsigned short    sa_family;    // adres ailesi, AF_xxx
    char              sa_data[14];  // protokol adresinin 14 byte'ı
};
sa_family pek çok değerden birini alabilir ama bizim örneğimizde AF_INET olacak. sa_data ise soketle ilgili hedef adres ve port numarası bilgilerini barındırır. Bunun garip olduğunu kabul ediyorum, yani herhalde bu bilgiyi kendi ellerinizle paketleyerek sa_data değişkenine yerleştirmek istemezsiniz değil mi?
struct sockaddr ile başa çıkabilmek için programcılar buna paralel bir yapı tasarlamışlar: struct sockaddr_in ("in" "Internet" anlamına geliyor.)
struct sockaddr_in {
    short int          sin_family;  // Adres ailesi
    unsigned short int sin_port;    // Port numarası
    struct in_addr     sin_addr;    // Internet adresi
    unsigned char      sin_zero[8]; // struct sockaddr ile aynı boyda
};
Bu yapı soket adresi elemanlarına erişmeyi kolaylaştırır. Dikkat etmeniz gereken bir nokta: sin_zero,[137] memset() işlevi kullanılarak tamamen sıfır ile doldurulmalıdır. Buna ek ve daha da önemli olarak bir struct sockaddr_in göstergesi struct sockaddr göstergesine dönüştürülebilir ve tersi de doğrudur. Yani her ne kadar socket() işlevi struct sockaddr* şeklinde bir veri beklese de siz gene de struct sockaddr_in kullanıp son anda gerekli dönüştürmeyi yapabilirsiniz! Ayrıca sin_family değişkeninin de struct sockaddr yapısındaki sa_family değişkenine karşılık geldiğini ve "AF_INET" olarak ayarlanması gerektiğini unutmayın. Son olarak sin_port ve sin_addr değikenlerinin de Ağ Byte Sırasında bulunmaları gerektiğini unutmayın!
"Fakat," diye itiraz edebilirsiniz, "nasıl olur da tüm yapı yani struct in_addr sin_addr Ağ Bayt Sıralamasına göre dizilebilir ki?" Bu soru tüm zamanların en kötü union'larından biri olan struct in_addr yapısının dikkatli olarak incelenmesini gerektirir:
// Internet adresi (tarihi sebeplerden ötürü korunmakta)
struct in_addr {
    unsigned long s_addr; // 32-bit yani 4 bytes
};
Evet, bir zamanlar kötü bir union idi. Neyse ki geçmişte kaldı. Eğer ina değişkenini struct sockaddr_in türünden tanımladı iseniz ina.sin_addr.s_addr 4 byte'lık Internet adresini gösterir (Ağ Bayt Sıralamasında). Aklınızda bulunsun eğer sizin sisteminiz kahrolası struct in_addr union'ını kullanıyor olsa bile yine de 4 byte'lık Internet adresine tamamen benim yaptığım gibi ulaşabilirsiniz (bunu #define'lara borçluyuz).


[136] Meraklısına not, Ağ Bayt Sıralaması aynı zamanda "Kıymetlisi Başta Bayt Sırası" (Big-Endian) ve Konak Bayt Sıralaması da "Kıymetlisi Sonda Bayt Sırası"(Little-Endian) olarak bilinir.
[137] Burada bulunmasının sebebi içinde bulunduğu veri yapısının boyunu struct sockaddr yapısının boyuna tamamlamaktır.
Önceki Üst Ana Başlık Sonraki
Düşük Seviye Duyarsızlığı ve Ağ Teorisi Başlangıç Veri Türlerini Dönüştür!
Bir Linux Kitaplığı Sayfası