Soket API
Bu bölümde, sonraki bölümlere alt yapı oluşturmak amacıyla, temel soket fonksiyonlarına sırasıyla değinmeye çalışacağız.
socket
Haberleşecek her iki taraf da ilk olarak birer soket oluşturmalıdır. Soketler, socket sistem çağrısı ile oluşturulmaktadır.
socket fonksiyonu başarılı olması durumunda bir soket oluşturur ve sonraki çağrılarda kullanılmak üzere, sokete ilişkin bir dosya betimleyicisi (file descriptor) döner. Başarısızlık durumunda ise -1 değerine geri dönmektedir. Oluşan soketin gerçekte ne olduğunu ve geri dönüş değerinin neyi gösterdiğini merak edebilirsiniz.
Unix sistemlerinde tüm Giriş/Çıkış işlemleri dosya betimleyicileri üzerinden, okuma ve yazma işlemleri şeklinde yapılmaktadır. Dosya betimleyicileri açık dosyalara erişimi sağlayan birer tamsayı değeridir. Örneğin, disk tabanlı bir dosya açıldığında, işletim sistemi bellekte o dosyaya ilişkin, adına dosya nesnesi (file object) denilen, bir alan oluşturur. Dosya ile ilgili daha sonraki okuma ve yazma işlemleri bu dosya nesnesi üzerinden yapılmaktadır. Bu dosya nesnesine ulaşmak için işletim sistemi her proses özelinde ayrıca bir dosya betimleyici tablosu (file descriptor table) denilen bir alan daha tutmaktadır. Gösterici dizisi şeklindeki bu tablonun her elemanı bir dosya nesnesinin adresini tutmakta ve dosya betimleyicileri de bu tabloda bir indeks değeri göstermektedir. open fonksiyonuyla bir disk tabanlı dosya açtığımızda fonksiyonun, başarılı olması durumunda, döndüğü değer aslında dosya betimleyici tablosundaki indeks değeridir.
soket fonksiyonunun argümanlarına geçmeden bu durumu aşağıdaki gibi bir örnek üzerinden gözleyebiliriz. Örneği test.c adıyla saklayıp aşağıdaki gibi derleyip çalıştırabilirsiniz.
Bir proses başlatıldığında dosya betimleyici tablosundaki ilk 3
giriş, standart okuma ve yazma işlemleri için, saklı durumdadır. Bu aşamadan sonra açılacak her dosya için dosya betimleyici tablodaki en düşük indeksli alan ayrılmaktadır. Örneğimizde disk tabanlı dosya için 3 numaralı girişin, soket için ise 4 numaralı girişin ayrıldığını görmekteyiz. Bu durumu görsel olarak aşağıdaki gibi gösterebiliriz.
Ortada gerçek anlamda bir dosya olmamasına karşın, soketler programcı tarafından bakıldığında gerçek birer dosyaymış gibi görünmektedir. Gerçek dosyalara ve soketlere aynı dosya betimleyici tablosu üzerinden erişildiğinden soketler üzerinde de dosya fonksiyonlarını kullanmak mümkün olmaktadır. Soketlerle çalışmak normal dosyalara göre daha karmaşık olduğundan okuma ve yazma işlemleri için ayrıca özel fonksiyonlar da bulunmaktadır.
Not: Soketlere ilişkin dosya sisteminde girişler oluşturulabilir. Bu tür soketlere (Unix Domain Socket) daha sonra değineceğiz.
socket fonksiyonunun aldığı argümanlar ve ilgilendiğimiz başlıca değerleri aşağıdaki gibidir.
domain: Kullanılacak olan protokol ailesini (protocol family) gösterir. bits/socket.h dosyasında sembolik sabitler şeklinde tanımlanmışlardır. Kullanacağımız başlıca değerler aşağıdaki gibidir.
Alan (Domain)
İletişim Ortamı
Adres Biçimi
Adres Yapı Türü
AF_UNIX
Aynı makina
Dosya yolu
sockaddr_un
AF_INET
IPv4 yoluyla ağ üzerinden
32-bit IPv4 adresi + 16-bit port numarası
sockaddr_in
AF_INET6
IPv6 yoluyla ağ üzerinden
128-bit IPv4 adresi + 16-bit port numarası
sockaddr_in6
socket fonkiyonuna, AF_UNIX geçirilmesi durumunda bir UNIX alan soketi oluşturulurken, diğer iki argüman için Internet alan soketi oluşturulmaktadır. Tablodaki diğer bilgilere yeri geldiğince değineceğiz.
type: type argümanı ile soketin tipi bildirilmektedir. bits/socket_type.h bu amaçla tanımlanmış sembolik sabitler bulunmaktadır. Başlıcaları aşağıdaki gibidir.
Tip
Anlamı
SOCK_STREAM
Güvenli, bağlantı temelli protokol (TCP)
SOCK_DGRAM
Güvensiz, mesaj temelli protokol (UDP)
SOCK_RAW
IP veya Ethernet gibi alt seviye protokol
SOCK_STREAM ile tanımlanan soketler stream soketi, SOCK_DGRAM ile tanımlananlar ise datagram soketi olarak isimlendirilmektedir.
protocol: Bu argümanın değeri diğer ikisine göre değişmektedir, çoğunlukla
0
değeri kullanılmaktadır.
bind
bind fonksiyonu bir soketi bir adresle ilişkilendirmek için kullanılmaktadır.
Parametre
Görevi
sockfd
socket çağrısından elde edilen dosya betimleyicisi
addr
Soketin bağlanacağı adres bilgilerinin tutulduğu alana ait gösterici
addrlen
Adres bilgilerinin tutulduğu alanın uzunluğu
socket fonksiyonunu incelerken, soketlerin birden çok alan için (AF_UNIX, AF_INET, AF_INET6) tanımlanabildiklerini görmüştük. Bu durumda farklı uzunluklardaki adres alanlarına ihtiyaç duyulmaktadır. Örneğin IPv4 ve IPv6 için soket adresleri sırasıyla, netinet/in.h dosyasında tanımlı, aşağıdaki yapı türlerinde saklanmaktadır. IPv4 için IP adresi 32 bit ile tutulurken IPv6 için 128 bit kullanıldığını hatırlayınız.
bind fonksiyonunu bu türlerden bağımsız yazabilmek için ayrıca genel bir adres türü olarak sockaddr türü tanımlanmıştır.
bind fonksiyonu çağrılırken gerçek adres türünden sockaddr türüne tür dönüşümü yapılmakta ve gerçek adres alanının uzunluğu addrlen parametresine geçirilmektedir. bind fonksiyonu ayrıca sa_family alanının değerine bakarak yapının geri kalan kısmının uzunluğunu ve adres formatını belirleyebilmektedir.
Şimdi soket ile ilişkilendireceğimiz adres alanını nasıl oluşturacağımıza bakalım. Daha basit olduğundan IPv4 adresini kullanacağız. sockaddr_in içindeki sin_addr alanına ait yapı ve tür tanımı aşağıdaki gibidir.
16 byte uzunluğundaki IPv4 için soket adres alanını (sockaddr_in) görsel olarak aşağıdaki gibi gösterebiliriz.
Birden çok byte'tan oluşan tam sayılar işlemci mimarisine göre bellekte iki farklı şekilde tutulabilmektedir. Örneğin, x86 mimarisinde sayının düşük anlamlı byte'ı düşük adreste tutulurken başka bir mimaride yerleşim tam tersi olabilir. x86 gibi düşük anlamlı byte'ın düşük adreste tutulduğu mimariler little endian olarak isimlendirilirken, sayının düşük anlamlı byte'ını yüksek adreste saklayan mimariler big endian olarak isimlendirilmektedir. Haberleşen sistemlerin byte sıralamaları farklı olabilmektedir bu yüzden ağ üzerinden gönderilecek olan bilgilerin byte sıralaması önem taşımaktadır. Ağ üzerinden gönderilen bilgiler geleneksel olarak big endian'dır (network byte order). Bu durumda soket adresine ilişkin alan içerisine IP adresinin ve port numarasının yazılma biçimi önem taşımaktadır. Çalışılan sistem big endian ise, port ve IP değerleri olduğu gibi yazılırken tersi durumda byte sıralamalarının değiştirilmesi gerekmektedir. Soket arayüzü, çalışılan sistem (host) ile ağ (network) arasındaki byte sıralaması uygunluğunu sağlamak için aşağıdaki yardımcı fonksiyonları barındırmaktadır.
listen
Stream soketi üzerinde dinleme yapmak için listen fonksiyonu kullanılır.
Soketler bir bağlantıyı başlatmak için kullanılabildikleri gibi gelen bağlantıyı kabul etmek için de kullanılmaktadırlar. Bağlantıyı başlatmak için kullanılan soketler aktif, bağlantıyı kabul edenler ise pasif olarak isimledirilmektedir. Bir soket socket fonksiyonuyla oluşturulduğunda aktiftir, listen fonksiyonu ile soket pasif hale geçirilerek bağlantıyı kabul eden tarafta olduğu belirtilir.
Parametre
Görevi
sockfd
socket çağrısından elde edilen dosya betimleyicisi
backlog
Cevap verilmeyi bekleyen kuyruktaki istek sayısı
backlog bekleyen bağlantı isteklerini sınırlamak için kullanılmaktadır.
accept
Gelen bağlantı istekleri accept ile kabul edilir. accept çağrıldığında bekleyen bir bağlantı isteği yoksa, normal şartlarda, yeni bir bağlantı isteği gelene kadar kod bloklanmaktadır.
Not: socket ile bir soket blokeli modda oluşturulmaktadır. Sonrasında soket fcntl ile blokesiz moda aşağıdaki gibi geçirilebilir. Bu durumda normalde bloklayan accept ve soketten okuma için kullanılan recv gibi fonksiyonlar blokesiz olarak çalışacaktır.
fcntl(sockfd, F_SETFL, O_NONBLOCK);
Parametre
Görevi
sockfd
socket çağrısından elde edilen dosya betimleyicisi
addr
Karşı taraftaki soket adresinin yerleştirileceği alanın adresi
addrlen
addr uzunluğunun tutulduğu adres
accept ile karşı tarafın adres bilgilerine ulaşılabilmektedir. İstekte bulunan soketin adresiyle ilgilenmiyorsanız addr ve addrlen için NULL ve 0 değerlerini geçirebilirsiniz. addrlen parametresi accept tarafından hem okuma hem de yazma amaçlı olarak kullanılmaktadır. accept çağrıldığında addrlen, addr için ayrılan alanın uzunluğunu gösterirken, accept döndüğünde o alana yazılan gerçek byte sayısını göstermektedir.
Not: Karşı tarafın adres bilgilerine daha sonra getpeername yardımcı fonksiyonuyla da ulaşılabilir.
accept bir bağlantı isteğini kabul ettiğinde yeni bir soket ile geri dönmekte ve haberleşme bu yeni soket üzerinden yapılmaktadır.
connect
Karşı tarafa bağlanma isteği connect ile gönderilir.
Parametre
Görevi
sockfd
socket çağrısından elde edilen dosya betimleyicisi
addr
Karşı taraftaki soket adresinin tutulduğu alana ait gösterici
addrlen
Adres bilgilerinin tutulduğu alanın uzunluğu
close
Soket bağlantısı close ile sonlandırılır.
shutdown
shutdown ile, geçirilen son argümanın değerine göre iletişim kanalı tek veya çift yönlü olarak kapatılabilir.
how
Durum
SHUT_RD
Soket okuma işlemine kapatılır
SHUT_WR
Soket yazma işlemine kapatılır
SHUT_RDWR
Soket okuma ve yazmaya kapatılır
Last updated
Was this helpful?