accept() -- "3490 Numaralı Portu Aradığınız İçin Teşekkürler"
Önceki Sistem Çağrıları veya Felaketleri Sonraki
accept() -- "3490 Numaralı Portu Aradığınız İçin Teşekkürler"
Sıkı durun -- accept() işlevi biraz gariptir! Neler oluyor? Şu oluyor: çok çok uzaklardan birileri connect() işevi ile sizin makinanızda sizin listen() ile dinlemekte olduğunuz bir porta bağlanmaya çalışıyor. Bu bağlantı talebi accept() ile kabul edilene dek kuyrukta bekleyecektir. Siz accept() işlevini çağırırsınız ve ona beklemekte olan çağrıyı kabul etmesini söylersiniz. O da size yepyeni bir soket dosya tanımlayıcısı döndürür sadece ve sadece söz konusu bağlantıya özel. Evet doğru duydunuz birdenbire elinizin altında iki soket dosya tanımlayıcısı oldu! Orjinal olanı halen port üzerinden dinleme işlemini gerçekleştirmek için kullanılıyor yeni olarak yaratılmış olan ise send() ve recv() işlevlerinde kullanılmak üzere emrinize amade. Hele şükür!
İşlevi şu şekilde çağırırsınız:
#include <sys/socket.h>

int accept(int sockfd, void *addr, int *addrlen);
sockfd dediğimiz listen() ile dinlediğiniz soket tanımlayıcıdır. Basit. addr yerel olarak kullandığınız struct sockaddr_in yapısını gösteren bir göstergedir. Gelen bağlantılarla ilgili bilgiler burada barındırılacak (yani bu yapıyı kullanarak gelen bağlantının hangi bilgisayar ve hangi porttan geldiğini öğrenebilirsiniz). addrlen yerel bir tamsayı değişkendir ve kullanılmadan önce accept() sizeof(struct sockaddr_in) değerini almalıdır. accept() işlevi bu değerden daha fazla sayıda baytı addr içine yerleştirmeyecektir. Eğer söz konusu değerden daha azını yerleştirirse o zaman da addrlen değerini, bunu yansıtacak şekilde değiştirecektir.
Tahmin edin ne diyeceğim? accept() hata durumunda -1 değerini döndürür ve errno değişkenine ilgili hata kodunu yerleştirir. Tahmin etmiş miydiniz? Gerçekten?
Biliyorum, bir seferde sindirmesi kolay değil. İsterseniz aşağıdaki örnek koda bakalım:
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MYPORT 3490    // kullanıcıların bağlanacağı port

#define BACKLOG 10     // kuyrukta bekleyecek bağlantı sayısı

main()
{
    int sockfd, new_fd;  // sock_fd ile dinle, new_fd yeni bağlantı için
    struct sockaddr_in my_addr;    // benim adres bilgim
    struct sockaddr_in their_addr; // bağlananın adres bilgisi
    int sin_size;

    sockfd = socket(AF_INET, SOCK_STREAM, 0); // hata denetimi yap!

    my_addr.sin_family = AF_INET;         // konak bayt sıralaması
    my_addr.sin_port = htons(MYPORT);     // short, ağ bayt sıralaması
    my_addr.sin_addr.s_addr = INADDR_ANY; // otomatik olarak benim IP'im
    memset(&(my_addr.sin_zero), '\0', 8); // geriye kalanı sıfırla

    // hata denetimi yapmayı sakın unutmayın:
    bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));

    listen(sockfd, BACKLOG);

    sin_size = sizeof(struct sockaddr_in);
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    .
    .
    . 
Lütfen dikkat edin: new_fd şeklindeki soket tanımlayıcıyı tüm send() ve recv() işlevleri için kullanacağız. Eğer sadece ve sadece tek bir bağlantıyı kabul edecekseniz close() ile sockfd üzerindeki dinleyici soketi kapatabilirsiniz böylece aynı port üzerinden başka bağlantı yaplamaz, eğer istediğiniz gerçekten bu ise.
Önceki Üst Ana Başlık Sonraki
listen() -- Biri Beni Arayabilir mi Acaba? Başlangıç  send() ve recv() -- Konuş Benimle Bebeğim!
Bir Linux Kitaplığı Sayfası