2016-12-27 27 views
0

我在iOS上使用UDP套接字。將其設置爲非阻止模式和/或模擬不良連接時,會遇到非常奇怪的行爲。sendto()在UDP套接字上的非相干行爲

爲了與通常fcntl設置非阻塞模式套接字:

fcntl(socketfd, F_SETFL, O_NONBLOCK); 

爲了模擬接觸不良我進/出丟包使用網絡鏈接Conditioneer有5/5和50KBps了限制(這保證在我的情況下,系統輸出緩衝區將在某個點滿)。

我通過sendto()發送數據,我用clock()printf()給電話打電話。


這裏是我的測試數據,以毫秒爲單位的數據:

  1. 阻塞,良好的連接:min 0/max 929//std 111
  2. 阻塞,連接不良:min 0/max 611/avg 38/std 84
  3. 非阻塞,良好的連接:min 0/max 6244/avg 601/std 1071
  4. 非阻塞,接觸不良:min 0/max 5774/avg 400/std 747

我也注意到,在案件2有與0 ms許多條目,這意味着sendto()已立即返回,這解釋了低案件的平均數和標準差。

在所有情況下,sendto()返回一個正值,對應於請求發送的字節數。

現在,有幾件事情我只是不明白:

  1. 阻塞模式,我希望它被阻塞,直到有可用的系統緩衝區來存儲數據,似乎不是該數據丟棄(由於呼叫立即返回)在非阻塞模式
  2. ,我希望sendto()返回時,它會阻止一個錯誤,從不是數據似乎調用塊,直到有實際上是空間來執行它

Th e行爲似乎是反轉的,但sendto從未報告失敗。

我在做什麼錯?


套接字創建:

int socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); 
// error checks 
setsockopt(socketfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); 

int tos = 0xB8; // VOICE 
setsockopt(socketfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); 

int rc = fcntl(m_iSocket, F_SETFL, O_NONBLOCK); 
if (rc != 0) { 
    // error of fcntl is notified 
} 

發送至:

sendto(socketfd, buffer, buffer_length, 0, (struct sockaddr *) &m_sRemoteHost, sizeof(m_sRemoteHost)) 

回答

2

你怎麼知道你的系統的發送緩衝區越來越滿了嗎?你只是假設因爲你已經對連接進行了速率限制,所以數據在發送緩衝區中備份。它更有可能在其他地方掉落。由於UDP不保證任何數據包將被傳送,因此數據包路徑上任何位置的任何軟件或硬件都可以隨時因任何原因自由丟棄。

UDP page on Wikipedia

UDP是最小的面向消息的傳輸層的協議,是 記錄在RFC 768 UDP提供不保證給上層協議 爲消息傳遞和UDP層保留沒有狀態 一次發送的UDP消息。由於這個原因,UDP有時被稱爲 ,因爲不可靠數據報協議。

+0

據我所知,UDP不提供任何保證。我也明白,不涉及流量控制。我無法理解的是,爲什麼sendto()調用的時間根據連接質量而變化如此之大,我也無法解釋它爲什麼會變化。是否有任何方法可以實際檢測到數據包由於傳輸緩衝區而被系統實際丟棄?鑑於沒有流量控制,這可以成爲緩衝區嗎? –