1. 程式人生 > >UDP迭代伺服器示例和UDP流量控制的缺失

UDP迭代伺服器示例和UDP流量控制的缺失

        我們知道, 有tcp伺服器, 也有udp伺服器, 這是按照協議來區分的。 如果按照服務方式來分, 還可以分為迭代伺服器和併發伺服器。

        所謂迭代伺服器, 就是單個程序/執行緒在單個埠上順序處理所有客戶端的請求, 而併發伺服器就不一樣了, 可以通過fork程序來併發處理多個客戶端的請求。

        在本文中, 我們主要來說說UDP迭代伺服器和UDP流量控制的缺失。

        我們來看一個最簡單的UDP伺服器(迭代伺服器):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main()
{
    struct sockaddr_in srvAddr;
    bzero(&srvAddr,sizeof(srvAddr));
    srvAddr.sin_family = AF_INET;
    srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    srvAddr.sin_port = htons(8765);
    int srvAddrLen = sizeof(srvAddr);

    int iSock = socket(AF_INET, SOCK_DGRAM, 0);  // udp
    bind(iSock, (struct sockaddr *)&srvAddr, sizeof(srvAddr));

    while(1)
    {
		char szBuf[65536] = {0};
        recvfrom(iSock, szBuf, sizeof(szBuf) - 1, 0, (struct sockaddr *)&srvAddr, (socklen_t*)&srvAddrLen);
        printf("msg from client [%s]\n", szBuf);
    }

    close(iSock);
    return 0;
}
       如果一個客戶端發資料過來, 顯然, 在while(1)中, printf會列印對應的資訊。 如果第二個客戶端過來, 顯然, 程式第二次進入while, 第二次列印對應的資訊。假設, 有n個客戶端連線過來, 那麼就迴圈n次列印資訊。 一切看似完美。

       假設有1000個客戶端幾乎同時發請求過來(高併發訪問), 那麼就會有這樣一種可能: 1000個客戶端請求到達後, udp伺服器可能還沒有處理完第一個請求, 那剩餘的請求怎麼辦呢? 肯定不能直接丟棄啊。

       是的, 作業系統協議棧會為這個udp socket所在的埠分配一個佇列, 併發而來的客戶端請求會被放到佇列中, 並遵循FIFO的原則進行處理。

       我們看到, 這種服務的方式是單個udp socket在8765埠上順序處理客戶端請求的, 這就是迭代伺服器。

        在極端情況下, 假設有1億個客戶端進行併發連線, 那麼, 這個佇列肯定是滿了, 多餘的請求會被直接丟棄, 而udp伺服器沒有能力對客戶端說: 尼瑪的, 你們請求太多了, 我處理不過來, 我壓力好大, 你們行行好, 控制下請求的量吧。

        udp伺服器沒這個能力, 這就是udp的流量控制缺失, 用人話來說, 就是udp沒有流量控制機制。

        先說這麼多。