UDP迭代伺服器示例和UDP流量控制的缺失
阿新 • • 發佈:2019-02-03
我們知道, 有tcp伺服器, 也有udp伺服器, 這是按照協議來區分的。 如果按照服務方式來分, 還可以分為迭代伺服器和併發伺服器。
所謂迭代伺服器, 就是單個程序/執行緒在單個埠上順序處理所有客戶端的請求, 而併發伺服器就不一樣了, 可以通過fork程序來併發處理多個客戶端的請求。
在本文中, 我們主要來說說UDP迭代伺服器和UDP流量控制的缺失。
我們來看一個最簡單的UDP伺服器(迭代伺服器):
如果一個客戶端發資料過來, 顯然, 在while(1)中, printf會列印對應的資訊。 如果第二個客戶端過來, 顯然, 程式第二次進入while, 第二次列印對應的資訊。假設, 有n個客戶端連線過來, 那麼就迴圈n次列印資訊。 一切看似完美。#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; }
假設有1000個客戶端幾乎同時發請求過來(高併發訪問), 那麼就會有這樣一種可能: 1000個客戶端請求到達後, udp伺服器可能還沒有處理完第一個請求, 那剩餘的請求怎麼辦呢? 肯定不能直接丟棄啊。
是的, 作業系統協議棧會為這個udp socket所在的埠分配一個佇列, 併發而來的客戶端請求會被放到佇列中, 並遵循FIFO的原則進行處理。
我們看到, 這種服務的方式是單個udp socket在8765埠上順序處理客戶端請求的, 這就是迭代伺服器。
在極端情況下, 假設有1億個客戶端進行併發連線, 那麼, 這個佇列肯定是滿了, 多餘的請求會被直接丟棄, 而udp伺服器沒有能力對客戶端說: 尼瑪的, 你們請求太多了, 我處理不過來, 我壓力好大, 你們行行好, 控制下請求的量吧。
udp伺服器沒這個能力, 這就是udp的流量控制缺失, 用人話來說, 就是udp沒有流量控制機制。
先說這麼多。