Sorunlu send() Durumları
Önceki İleri Teknikler Sonraki
Sorunlu send() Durumları
Hatırlarsanız send() ve recv() -- Konuş Benimle Bebeğim! bölümünde send() işlevinin sizin istediğiniz kadar veriyi bir anda gönderemeyebileceğinden bahsetmiştim. Tam olarak böyle yani siz ondan 512 byte göndermesini istersiniz ama o sadece 412 tanesini yollar. Peki geriye kalan 100 bayta ne oldu?
Bu veriler hala bizim küçük tampon bölgemizde gönderilmeyi bekliyorlar. Kontrolünüz dışındaki bir takım sebeplerden ötürü işletim sistemi çekirdeği mevcut veriyi bir seferde göndermemeye karar verdi ve iş başa düştü.
Sorunu halletmek için şöyle bir işlev kullanabilirsiniz:
#include <sys/types.h>
#include <sys/socket.h>

int sendall(int s, char *buf, int *len)
{
    int total = 0;        // gönderdigimiz byte miktari
    int bytesleft = *len; // eksik kalan byte miktari
    int n;

    while(total < *len) {
        n = send(s, buf+total, bytesleft, 0);
        if (n == -1) { break; }
        total += n;
        bytesleft -= n;
    }

    *len = total; // gönderilen toplam bayt miktarı

    return n==-1?-1:0; // sorun varsa -1, işlem tamamsa 0 döner
} 
Bu örnekte, s üzerinden veriyi göndermek istediğimiz soketi, buf veriyi barındıran bellek bölgesini (buffer) ve len de tampondaki byte sayısını gösteren sayıya işaret eden int türünde bir göstergedir.
Hata durumunda işlev -1 değerini döndürür (ve errno hata değişkeni de send() işlevi sayesinde gerekli hata kodunu barındırır.) Ayrıca gönderilebilmiş olan byte sayısı da len parametresinden depolanır. Bu sayı sizin göndermek istediğiniz sayıya eşit olacaktır (hata oluşması durumu haricinde). sendall() işlevi verinin tamamını yollamak için elinden geleni yapacaktır ancak bir hata ile karşılaşırsa size geri dönecektir.
Hemen bir örnek verelim:
char buf[10] = "Beej!";
int len;

len = strlen(buf);
if (sendall(s, buf, &len) == -1) {
    perror("sendall");
    printf("We only sent %d bytes because of the error!\n", len);
} 
Peki ya verinin sadece bir kısmı diğer tarafa erişebildiğinde diğer tarafta ne olup biter? Eğer gelen paketlerin boyu değişken ise bunları alan taraf bir paketin ne zaman bittiğini, diğerinin ne zaman başladığını nasıl anlar? Evet, gerçek dünya senaryoları insanları biraz düşünmeye zorlar. Büyük ihtimalle yukarıdaki problemlerle başa çıkabilmek için yapmanız gereken veriyi paketlemek (encapsulate) olacaktır (veri paketleme bölümünü hatırladınız mı?) Ayrıntılar için okumaya devam edin!
Önceki Üst Ana Başlık Sonraki
select() -- Eşzamanlı G/Ç Çoğullama Başlangıç Veri Paketlemesi Hazretleri
Bir Linux Kitaplığı Sayfası