2013-05-08 197 views
1

如果我發送1000個「Hello World!」 UDP消息(12字節+ 28 IP/UDP開銷),我觀察到在接收端我只緩衝658(總是相同的數字,658 * 40 = 26320字節)。我這樣做,通過在服務器上睡眠時發送UDP消息(創建套接字之後)。沒有填充接收緩衝區的UDP緩衝區溢出?

奇怪的是服務器上的SO_RCVBUF選項是42080字節。所以,我想知道爲什麼我不能緩衝1000條消息。你知道剩下的15760字節花在哪裏嗎?

下面的服務器代碼(其中包含distrib.h的插座和信號處理功能,基本的錯誤處理包裝):

#include "distrib.h" 

static int count; 
static void sigint_handler(int s) { 
    printf("\n%d UDP messages received\n",count); 
    exit(0); 
} 

int main(int argc, char **argv) 
{ 
    struct addrinfo* serverinfo; 
    struct addrinfo hints; 
    struct sockaddr_storage sender; 
    socklen_t len; 
    int listenfd,n; 
    char buf[MAXLINE+1]; 

    if (argc != 2) { 
    log_error("usage: %s <port>\n", argv[0]); 
    exit(1); 
    } 

    Signal(SIGINT,sigint_handler); 

    bzero(&hints,sizeof(hints)); 
    hints.ai_family = AF_INET;  
    hints.ai_socktype = SOCK_DGRAM; 
    hints.ai_protocol = IPPROTO_UDP; 
    Getaddrinfo("127.0.0.1", argv[1], &hints, &serverinfo); 

    listenfd = Socket(serverinfo->ai_family, serverinfo->ai_socktype, 
      serverinfo->ai_protocol); 
    Bind(listenfd, serverinfo->ai_addr,serverinfo->ai_addrlen); 
    freeaddrinfo(serverinfo); 

    count =0; 
    sleep(20); 
    while(true) { 
    bzero(buf,sizeof(buf)); 
    len = sizeof(sender); 
    n = Recvfrom(listenfd, buf, MAXLINE, 0, (struct sockaddr*)&sender,&len); 
    buf[n]='\0'; 
    count++; 

    } 

    close(listenfd); 

    return 0; 
} 
+0

MAXLINE的價值是什麼? – thuovila 2013-05-08 11:34:30

+0

你確定所有郵件都已發送嗎?服務器和客戶端程序都在同一臺計算機/網絡上嗎? – 2013-05-08 11:47:03

+0

如果你在Linux上,你是否檢查_netstat -su_ [ref](http://stackoverflow.com/questions/10899937/udp-packet-drops-by-linux-kernel) – thuovila 2013-05-08 11:47:52

回答

4

這更多的信息做反向計算 - 你的緩衝區是42080,它在開始丟棄之前緩衝了658個數據包。現在42080/658 = 63.95,因此它看起來像是將每個數據包計爲64個字節,並且如果目前緩衝的數據包的總大小等於或超過限制,則丟棄數據包。由於它緩衝了整個數據包,實際上它的緩衝區稍稍超過限制。

爲什麼64字節而不是40?也許它包含了一些排隊開銷,或者它可能是以2的倍數來對齊,或者也可能是兩者的某種組合。

1

我沒有一個完整的答案,但我測試了這個在我的Linux框和這是我觀察到的。

當我發送一個「Hello World!\ n」結尾爲'0'。我得到:

客戶:

$./sendto 
sent 14 bytes 

插座 「的Recv-Q」 已經768個字節(似乎有可能它以字節爲單位,沒有檢查SS源):

$ ss -ul|grep 55555 
UNCONN  768 0    127.0.0.1:55555     *:*  

當我送1000個包我得到:

$ ./sendto 
sent 14000 bytes 

的Recv-Q:

$ ss -ul|grep 55555 
UNCONN  213504 0    127.0.0.1:55555     *:*  

您的服務器(後CTRL-C):

$ ./recvfrom 55555 
^C 
278 UDP messages received 

順便七百六十八分之二十一萬三千五百零四= 278.快速實驗的我想不出什麼設置調整,以增加緩衝量。另外,我不知道爲什麼接收到的數據包在這個隊列中佔用這麼多空間。許多元數據可能?在你的osX上,丟棄的數據包在netstat -su中顯示。

編輯:

UNCONN  213504 0    127.0.0.1:55555     *:*  
skmem:(r213504,rb212992,t0,tb212992,f3584,w0,o0,bl0) 

緩衝的213504個字節是上面的RB值512個字節:與SS -ulm,打印 「插座存儲器使用」 更詳細的附加觀察。可能不是巧合,但需要閱讀內核源代碼才能找到答案。

你是否檢查過一個UDP數據報在osX上佔用多少?

編輯2: 這仍然不是在OSX一個合適的答案,但在Linux上我發現,增加分配給內核內存接收緩衝區讓我來緩衝發送的所有1000個數據包。

大材小用了一點,但我用這些(免責聲明)隨機調整的緩衝值可能會嚴重弄亂你的網絡和內核):

net.core.rmem_max=1048568 
net.core.rmem_default=1048568