+----------------------------------------------------------------------+
| İstemci | Sunucu |
|----------------------------------------------------------------------|
| | Soket oluştur, socket() |
| |--------------------------------------------|
| Soket oluştur, socket() | Adres bilgilerini yerleştir sockaddr_in |
| |--------------------------------------------|
| | Soket adını adresi ile ilişkilendir bind() |
| |--------------------------------------------|
| | Soketi dinlemeye geç, bind() |
|-------------------------+--------------------------------------------|
| Bağlantı yap, connect() | Bağlantıyı kabul et, accept() |
|-------------------------+--------------------------------------------|
| Veri gönder, send() | Veri al, recv() |
|-------------------------+--------------------------------------------|
| Veri al, recv() | Veri gönder, send() |
|-------------------------+--------------------------------------------|
| ... | ... |
| Diğer işlemler | Diğer işlemler |
| ... | ... |
|-------------------------+--------------------------------------------|
| Soketi kapat, close() | Soketi kapat, close() |
+----------------------------------------------------------------------+
3.1. Soket Türleri
Tanımlı pek çok soket türü vardır. Ancak u dökümanda en çok kullanılan 3 türden bahsedilecektir.
SOCK_STREAM: Sıralı, güvenli, iki yollu, bağlantı yönelimli (connection oriented) veri akışı
sağlar. Veri alışverişinden önce bağlantı (connect) yapılmış olmalı. Paketin kaybolmadığını veya
birden çok gelmediğini uygulama katmanına garanti eder. Kabul edilebilir bir süre içerisinde veri
transferi sağlanamazsa bağlantı yok varsayılır.
SOCK_DGRAM: Datagram bağlantısı sağlar. Datagramlar, bağlantısız (connectionless), güvenilir
olmayan paketlerdir.
SOCK_RAW: TCP/IP ye raw olarak (herhangi bir format ve sınır olmadan) ulaşmayı sağlar.
Raw soketler başlı başına bir konu olup detaylı bilgi için Murat Balaban'ın yazdığı
http://www.acikkod.org/yayingoster.php?id=34
dökümanından faydalanabilirsiniz. Datagram ve
stream soketleri
2.3.
Taşıma Katmanı kısmında tartışıldı.
3.2. Veri Dönüşümleri
İnsanların soldan sağa veya sağdan sola alfabelere sahip olmaları gibi işlemciler de byte'ları
saklarken önemli byte'ın solda veya sağda olmasına göre sınıflandırılır. Buna endianness da denir.
Arap rakamlarında olduğu gibi (İngilizce veya Türkçede kullandığımız rakamlar) önemli byte'ın
solda olduğu sıralamaya big-endian denir. Önemli byte'ın en sağda olduğu sıralama ise Little Endian
olarak adlandırılır.
Bütün işlemciler kendi sıralamasını seçmiştir. i386 ve klonu olan işlemciler little endian'dır. Sun
Sparc, Motorola 68K ve PowerPC big endian kullanır. Java Sanal İşlemcisi (Java VM) de big
endian kullanır.
Farklı iki işlemcisi olan makineler birbirileri ile haberleşecekleri zaman (IPC), bu veri dönüşümünü
yapmazlar ise haberleşemezler.
Ağ protokolleri de kendi sıralamasını seçmelidir. Aksi takdirde iki farklı mimarideki bilgisayar IPC
yaparak birbirileri ile haberleşecekleri zaman anlaşamayacaklardır. TCP/IP big endian sıralamasını
kullanır. Bunun anlamı şu: Herhangi bir paket (IP adresi, paket uzunluğu, kontrol değeri gibi)
gönderileceği zaman en önemli byte'ı önce gönderilir ve alınır.
İki tür byte sıralaması vardır. En önemli byte'ın önde geldiği sıralama ki buna
Network Byte
Sıralaması denir ve önemli byte'ın sonra geldiği dıralama. Buna da
Host Byte Sıralaması denir. Bu
ikisi arasındaki dönüşümler aşağıdaki dört fonksiyon tarafından yapılmaktadır:
#include
uint32_t htonl(uint32_t hostlong); /* Host to Network Long */
uint16_t htons(uint16_t hostshort); /* Host to Network Short */
uint32_t ntohl(uint32_t netlong); /* Network to Host Long */
uint16_t ntohs(uint16_t netshort); /* Network to Host Short */
Eğer iki host da little endian ise veri transferinden önce network byte sırasına çevirilmeli. Alınan
tarafta tekrar little endian'a çevrilir.
Şu senaryoyu dikkatle inceleyelim inceleyelim: Intel bir makine internet üzerinden SPARC makine
ile haberleşecek. Veri olarak 192.168.1.254 gibi bir IP adresini düşünelim. Intel işlemci little endian
olarak bunu 0xFE01A8C0(254 1 168 192) şeklinde tutar ve FE-01-A8-C0 sırasıyla bunu gönderir.
SPARC makine bunu aynı sırada alacak ve bu sırada kullanacak. Çünkü big endian kullanır ve
önemli olan en başta gelir. Dolayısıyla SPARC bu IP adresini 254.1.168.192 olarak algılar.
Programcı hostlarda hangi sıralamanın kullanıldığını bilmek zorunda değil. Yukarıdaki dönüştürücü
fonksiyonlar kendi işlemcileri ile ilgili dönüşümleri otomatik olarak yapacaktır.
Veriler ağ üzerinde network byte sırası ile dolaşacaktır. Veriyi alan host makina ntohl ile bu veriyi
kendi anladığı sıraya çevirecektir.
3.3. Sistem Çağrıları
Adres ataması:
Gerek sunucu, gerekse istemci internet adres bilgilerini tutmak için sockaddr_in yapısını kullanır.
Bu yapının açılımı şu şekildedir:
struct sockaddr_in {
short
sin_family;
unsigned short
sin_port;
struct in_addr
sin_addr;
char
sin_zero[8];
}
Bu yapı içerisinde bir başka yapı daha vardır. Bu yapı in_addr yapısıdır ve açılımı şöyledir:
struct in_addr {
union
{
struct { u_char s_b1, s_b2, s_b3, s_b4;
} S_un_b;
struct { u_short s_w1, s_w2; } S_un_w;
u_long S_addr;
}
S_un;
}
Bu yapıları doğrudan kullanmayacağız; o nedenle rahat olun. Ancak ilk yapının temel yapımız
olduğunu unutmayın. Bu yapı içerisinde IP adreslerini ve port numaralarını saklayacağız.
İnsanlar bir bağlantı gerçekleştirecekleri zaman genelde host isimlerini kullanırlar. Oysa internetteki