21 Mart 2016 Pazartesi

TCP Sliding Window

TCP Sliding Window
TCP Sliding Window protokolü gönderen ve alan tarafların Send Window ve Receive Window kullanarak, paketleri takip etmeleri kuralına dayanır. Bu konuyu en iyi anlatan yazı TCP/IP Guide. Özellikle Send ve Receive yazılarına mutlaka bakmak lazım.

Programlama kitaplarında Send Window yerine Send Buffer kelimesi kullanılıyor. Sanırım ikisi de aynı şey.

Sliding Window sayesinde TCP şu işlevleri sağlayabilir.

1. Guaranteed delivery. If a packet is lost, TCP will detect and resend it.
2. Packet ordering. If packets arrive out of order, TCP can reassemble them in the correct order.
3. Transmission rate control. TCP allows the receiver to tell the sender to slow down or speed up as necessary.


Kablonun Çekilmesi
Eğer ethernet kablosunu çekersek ve bir müddet beklersek bile TCP Sliding Window tekrar gönderim kurallarını işlettiği için bağlantı kopmaz.

Sliding Window Büyüklüğü
Sliding Window'un ne kadar büyük olması gerektiği yani kaç paketi takip etmesi gerektiği teorik olarak hesaplanabilir.

Send Window
Şekilde Send Window'un nasıl çalıştığı görülebilir.

TCP Output Queue - Category #2 + Category #3

TCP socketinde bir "output queue" bulunur. Linux üzerinde bu kuyrukta kaç byte veri beklediğini görmek için bir ioctl komutu bulunmakta.
int value;
error = ioctl(tcp_socket, SIOCOUTQ, &value);
SIOCOUTQ parametresinin açıklaması burada . Aslında buradaki header dosyasına bakınca açıklama olarak şunu görmek mümkün.

#define SIOCOUTQ        TIOCOUTQ        /* output queue size (not sent + not acked) */

Yani benim anladığım yukarıdaki şekildeki Category#2 + Category#3  'ün toplamını veriyor.

Send Buffer Büyüklüğü

Buradan aldığım aşağıdaki şekilden de görülebildiği gibi output kuyruğunun büyüklüğünü ayarlayabilmek mümkün. Bunun için SO_SNDBUF seçeneği kullanılıyor.

Soketin Send Buffer büyüklüğü şöyle öğrenilebilir.
int sockfd, sendbuff;
socklen_t optlen;

 // Get buffer size
optlen = sizeof(sendbuff);
res = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);
Yine aynı şekilde Send Buffer büyüklüğü şöyle atanabilir.
// Set buffer size
sendbuff = 98304;
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));
Linux bir şekilde Send Buffer büyüklüğünü verilen değerin iki katı olarak kullanıyor.
SO_SNDBUF
     Sets or gets the maximum socket send buffer in bytes.  The  ker-
     nel doubles this value (to allow space for bookkeeping overhead)
     when it is set using setsockopt(), and  this  doubled  value  is
     returned  by  getsockopt().   The  default  value  is set by the
     wmem_default sysctl and the maximum allowed value is set by  the
     wmem_max sysctl.  The minimum (doubled) value for this option is
     2048.

Send buffer'ın büyüklüğünü ayarlamak yerine, aynı dosya sistemindeki gibi Buffered I/O yapabilme fikrinin uygulandığını da gördüm.
FILE *f_recv = fdopen(sock, "wb");
FILE *f_send = fdopen(sock, "rb");

// some IO here.

close(sock);
fclose(f_recv);
fclose(f_send);

Receive Window
Receive Buffer Büyüklüğü
SO_RCVBUF ile socket receive buffer büyüklüğü ayarlanabiliyor.

Büyüklüğü almak için şöyle yapılır.
int recvBufSize;
int err = getsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                     (char*)&recvBufSize, sizeof(recvBufSize));
Büyüklüğü atamak için ise
int recvBufSize = /* usage specific size */;
int err = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                     (const char*)&recvBufSize, sizeof(recvBufSize));





Hiç yorum yok:

Yorum Gönder