Domain Soketleri ve Internet Soketleri



Yüklə 181,98 Kb.
Pdf görüntüsü
səhifə5/7
tarix17.10.2017
ölçüsü181,98 Kb.
#5100
1   2   3   4   5   6   7

hiçbir makine host ismini kullanmaz. "cclub.ktu.edu.tr" bir host ismidir. 193.140.168.77 bu hostun

sahip olduğu IP adresidir. Host isimlerini IP adreslerine çeviren sistemlere DNS (Domain Name

Server)   denir.   İşletim   sistemi   bize   DNS   işlemlerini   yapmak   için   kütüphane   sunmaktadır.   IP

dönüşümü yapmak için kütüphane çağrılarından gethostbyname() 'i kullanabiliriz.

#include

struct hostent* host;

host = gethostbyname("cclub.ktu.edu.tr");

Soket Oluşturma:

İki programın haberleşmesi için öncelikle her iki tarafta da soket açılması gerekir.

int socket(int domain, int type, int protocol);

socket() fonksiyonunun ikinci parametresi soketin tipidir. Buraya:

SOCK_STREAM

SOCK_DGRAM

SOCK_RAW

SOCK_SEQPACKET

SOCK_RDM

SOCK_PACKET

gibi   soket   türlerini   yazabiliriz.   İlk   ikisini   yukarıda   anlattım.   Diğerlerinin   ne   anlama   geldiği   şu

aşamada önemli değildir. Yalnızca biz SOCK_STREAM tipini kullandığımız için ikinci parametre

olarak bunu verdiğimizi bilin. Yani bu bir stream sunucu soket uygulamasıdır.

Üçüncü parametresi protocol tipini belirler. Hali hazırda 5 protokol türü vardır :

AF_UNIX (UNIX internal protocols)

AF_INET (ARPA Internet protocols)

AF_ISO (ISO protocols)

AF_NS (Xerox Network Systems protocols)

AF_IMPLINK (IMP "host at IMP" link layer)

Soket ile ilgili tanımlamaların başlık dosyaları  ve  dir.



Veri Alış-verişi:

Birbiri  ile  bağlantısı  yapılmış  iki  soket  arasında  artık  veri  alış-verişine  başlayabiliriz.  Buradaki

veriler  karşıya taşınması  gereken gerçek veriler olabileceği gibi, karşıya yapması gereken işleri

bildiren bir komut listesi olabilir. Her şey, iki program arasında tarafınızdan tanımlanmış protokol

çerçevesinde olacaktır.

write() ve read() fonksiyonları aynı zamanda dosya işlemleri için de kullanılır.  send() ve recv() ise

bu fonksiyonların soketler için özelliştirilmiş halidir.

int send(int s, const void *msg, int len, unsigned int flags);

int recv(int s, const void *msg, int len, unsigned int flags);



4. Sunucu Soket Programı

4.1. Sistem Çağrılarının Kullanımı

Bu kadar teorik bilgiden sonra bir uygulama yapmaya geçebiliriz. 2222 numaralı portta çalışan basit

bir sunucu programı üzerinde olayları inceleyelim. Bundan sonra üzerinde çalışacağımız kodlar

sunucu için yazılmaktadır. İstemci program olarak standart telnet programını kullanacağız. Mimari

olarak sunucu yazılımların, istemci yazılımlardan farklı olduğunu unutmayın. Aşağıdaki kodları gcc

C derleyicisi kullanarak yazdım. Ancak bu kodlar tamamen standart olup Windows altındaki Visual

C derleyicisi ile de çalışabilir. Değişik platformlarda sorun yatmasın diye kod içerisinde Türkçe

karakter kullanmadım.

Önce port numaramızı belirleyelim:

#define PORT 2222

Sıra soket oluşturmada:

int sockfd;

sockfd=socket(AF_INET,SOCK_STREAM,0); 

if (sockfd<0) { 

  perror("socket"); 

  exit(1); 

}

Burada verdiğim kodlar tek başına çalışmaz. Daha kolay anlaşılsın diye programdan parçalar bir



araya getiriyorum. En sonunda çalışabilir kodun tamamını vereceğim. Bu işlemlere başlamadan

önce bazı header (.h) dosyalarının yüklenmesi gerekir. Bunları da kodun tamamında görebilirsiniz.

Yukarıdaki kodu incelersek: Soket oluşturma işlemini socket() fonksiyonu ile yapıyoruz.

socket() fonksiyonu geriye bir tamsayı değer döndürür. Hata oluşumunda bu değer -1'dir. Eğer hata

oluşmazsa geri dönen değer soketin tanımlayıcı numarasıdır. Bu numara en başta bahsettiğimiz gibi

dosya tanımlayıcısıdır. Bu numarayı kodda görüldüğü gibi sockfd değişkenine atatım. Bu işlemden

sonra   soketi   takip   etmek   için   artık   sockfd   değişkenini   kullanacağım.   Oluşturulan   her   soket   bu

şekilde ayrı bir numara alır.

Hata kontrolü yapmaya özen gösterin. Aksi halde zamanızın büyük bir kısmını programdaki hataları

ayıklamak ile geçirirsiniz.

Şimdi port numarasının atamasını yapalım:

if(bind(sockfd,(struct   sockaddr   *)&my_addr,sizeof(struct   sockaddr))   ==

-1) { 

  perror("bind"); 



  exit(1); 

}

bind()   fonksiyonu   soketi   isimlendirir.   socket()   ile   oluşturulmuş   bir   soket   için   isim   uzayında



(bellekte) vardır ancak bir isme sahip değildir. Bind işlemi belirtilen port numarasını ve gerekli

sistem   kaynaklarını   işletim   sisteminden   ister.   Eğer   bu   işlemi   yapmazsanız   işletim   sistemi   port

havuzundan herhangi bir port atar. Port numarasını belirlemezseniz, diğer insanlar sizin programla

haberleşecek programlar yazamaz. bind()  fonksiyonu aynı zamanda  sizi   bir veya daha fazla  ağ




arabirim kartından (Network Interface Card) yalıtır. Ağ üzerindeki her host bir NIC'a sahiptir ve her

NIC en az bir IP adresine sahiptir. addr.sin_addr değeri olarak INADDR_ANY yazmakla işletim

sistemine   host   üzerinde   bulunan   mümkün   bütün   IP   adreslerinden   bağlantı   kabul   edeceğinizi

söylüyorsunuz.   Bunu   istemiyorsanız   makinenin   sahip   olduğu   IP   numaralarından   birini,   hizmet

vermek üzere seçebilirsiniz. Eğer üzerinde bulunduğunuz makine bir firewall ise belirlenmiş bir

IP'yi kullanmak yararınıza olacaktır. Bu şekilde firewall'un yalnızca bir yüzü hizmet sunacaktır.

if (listen(sockfd, 5) == -1) {

  perror("listen");

  exit(1);

}

bind()   işleminden   sonra   sunucumuz   artık   istemcileri   beklemeye  başlayabilir.   İstemcilerin   kabul



edilebilmesi için sunucunun öncelikle dinlemeye geçmesi gerekir. Bunun için listen() fonksiyonunu

kullanır. Bu çağrı, soketin özelliklerinde bazı değişiklikler yapar. Örneğin soketi dinleme moduna

geçer ve bu soketi veri taşıması için kullanamazsınız. listen(), çağrıldıktan sonra parametre olarak

belirttiğiniz   kadar   bir   bekleme   kuyruğu   oluşturur.   Yukarıda   parametre   olarak   5   verdik.   Bunun

anlamı:   Sunucu   mevcut   bağlantıya   hizmet   verirken   gelecek   ilk   5   istek   bekleme   kuyruğuna

konulacak. Sunucu sırayla bunlara hizmet verecek.

Artık sunucu bağlantı kabul etmek için soketi dinlemeye almıştır. Herhangi bir istemcinin bağlantı

isteğini   accept()   çağrısı   ile   yakalayacağız.   Kabül   fonksiyonu  programı   G/Ç   bekleme   durumuna

sokar. Dolaysıyla programımız işletim sistemi tarafından bloke edilir ve bağlantı isteği geldiğinde

tekrar uyandırılır.

int accept(int s, struct sockaddr *addr, int *addrlen);

Kabül   işlemi,   gelen   isteği   yeni   bir   soket   ile   karşılar.   Çünkü   mevcut   soketimiz   dinleme

durumundadır ve veri taşıma işlemi gerçekleştiremez.

Şimdi programımızın tamamlandığını ve cclub.ktu.edu.tr hostunda çalıştığını varsayalım.

cclub:~> telnet cclub.ktu.edu.tr 2222

Geçici olarak telnet programını istemci olarak kullandım. "telnet" i bir echo istemcisi gibi düşünün.

Sunucu   ne   gönderirse   onu   ekrana   basar.   2222   portuna   bağlantı   isteği   gönderdiğimizde   sunucu

programımız   bize   yeni   bir   soket   açıp   bağlantımızı   kabul   edecek.   Telnet   ile   sunucumuzun

konuşmaması için hiçbir neden yok.

İstemcilerin adres bilgileri, bağlantı kabülü sırasında alınır. accept() fonksiyonun son parametresi

bir girdi değil çıktıdır. Bağlantı sırasında bu yapı doldurulup programa döndürülür. Biz programa

dönen   adres   bilgilerini   kullanarak   programlarımıza   biraz   renk   katabiliriz.   Örneğin,   istemcinin

adresini alıp bir yasak dosyasında var mı diye kontrol ederiz. Eğer varsa bağlantıyı red ederiz.

Bağlantıları kısıtlayan /etc/hosts.deny ve serbestlik tanıyan /etc/hosts.allow dosyalarını hatırlayın.

Sanki bir şeyler hatırlar gibi olduk değil mi?

int fd, client_size; 

struct sockaddr_in client_addr; 

client_size = sizeof(struct sockaddr_in); 

fd = accept(sockfd, (struct sockaddr *)&client_addr, &client_size)); 

printf("Merhaba %s",inet_ntoa(client_addr.sin_addr));

Sunucumuza   bir   bağlantı   yapıldığında   sunucu   ekrana   "Merhaba   193.140.168.54"   gibi   bir   şey

yazacak. Gördüğünüz gibi bağlantı yapanın adresini de aldık.




Yüklə 181,98 Kb.

Dostları ilə paylaş:
1   2   3   4   5   6   7




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©www.genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə