2011-11-13 26 views
7

的我無法做出如何以及爲什麼下面的代碼段工作的意義:影響SO_SNDBUF

/* Now lets try to set the send buffer size to 5000 bytes */ 
    size = 5000; 
    err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int)); 
    if (err != 0) { 
     printf("Unable to set send buffer size, continuing with default size\n"); 
    } 

如果我們檢查發送緩衝區的價值,這的確是正確設置爲5000 * 2 = 10000 但是,如果我們嘗試發送的發送緩衝區大小超過發送緩衝區大小,它確實會發送全部。例如:

n = send(sockfd, buf, 30000, 0); 

    /* Lets check how much us actually sent */ 
    printf("No. of bytes sent is %d\n", n); 

此打印出30000

究竟是如何做這項工作?發送緩衝區大小限制爲10000的事實是否有影響?如果確實如此,究竟發生了什麼?某種破碎?

更新:如果套接字處於非阻塞模式,會發生什麼情況?我嘗試以下:

  1. 改變緩衝器大小爲10000(5000 * 2)導致16384個字節被髮送
  2. 更改緩衝區大小爲20000(10000 * 2)使30000個字節被髮送

再次,爲什麼?

回答

11

設置SO_SNDBUF選項對TCP和UDP的影響是不同的。

  • 對於UDP此設置限制對數據報的尺寸,即更大的東西將被丟棄。
  • 對於TCP,它只是爲給定的套接字設置了內核內緩衝區的大小(對頁邊界和上限進行了一些舍入)。

因爲它看起來像你說的是TCP,你所觀察的效果是由插座被阻塞模式,所以send(2)阻塞,直到內核可以接受所有的數據,和/或網絡解釋將數據異步排隊並將其推送到網卡,從而釋放緩衝區中的空間。

此外,TCP是一個流協議,它不保留任何「消息」結構。其中一個send(2)可以對應另一側的多個recv(2),反之亦然。將其視爲字節流。

+0

如果套接字處於非阻塞模式會發生什麼情況? 我嘗試了以下操作: 1)將緩衝區大小更改爲10000將導致發送16384個字節 2)將緩衝區大小更改爲20000會導致發送30000字節 爲什麼? – Arun

+0

@阿倫:那只是四捨五入。爲什麼這一切都很重要?你不應該依賴這個事實,即緩衝區正好是* n個字節。內核可以分配更多。 –

+1

首先,內核不會按照@yi_H指出的那樣緩衝區大小。然後,網絡堆棧就您的進程異步*操作。嘗試以下方法 - 開始寫入套接字,但*不讀取其他大小*。最終你會得到一個簡短的(內核接受更少的字節,然後你給它)或失敗的寫。 –

4

SO_SNDBUF配置套接字實現在內部使用的緩衝區。如果你的套接字是非阻塞的,你只能發送到配置的大小,如果你的套接字被阻塞,那麼你的呼叫就沒有限制。