我在iOS上使用UDP套接字。將其設置爲非阻止模式和/或模擬不良連接時,會遇到非常奇怪的行爲。sendto()在UDP套接字上的非相干行爲
爲了與通常fcntl
設置非阻塞模式套接字:
fcntl(socketfd, F_SETFL, O_NONBLOCK);
爲了模擬接觸不良我進/出丟包使用網絡鏈接Conditioneer有5/5和50KBps了限制(這保證在我的情況下,系統輸出緩衝區將在某個點滿)。
我通過sendto()
發送數據,我用clock()
和printf()
給電話打電話。
這裏是我的測試數據,以毫秒爲單位的數據:
- 阻塞,良好的連接:
min 0
/max 929
//std 111
- 阻塞,連接不良:
min 0
/max 611
/avg 38
/std 84
- 非阻塞,良好的連接:
min 0
/max 6244
/avg 601
/std 1071
- 非阻塞,接觸不良:
min 0
/max 5774
/avg 400
/std 747
我也注意到,在案件2
有與0 ms
許多條目,這意味着sendto()
已立即返回,這解釋了低案件的平均數和標準差。
在所有情況下,sendto()
返回一個正值,對應於請求發送的字節數。
現在,有幾件事情我只是不明白:
- 阻塞模式,我希望它被阻塞,直到有可用的系統緩衝區來存儲數據,似乎不是該數據丟棄(由於呼叫立即返回)在非阻塞模式
- ,我希望
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))
據我所知,UDP不提供任何保證。我也明白,不涉及流量控制。我無法理解的是,爲什麼sendto()調用的時間根據連接質量而變化如此之大,我也無法解釋它爲什麼會變化。是否有任何方法可以實際檢測到數據包由於傳輸緩衝區而被系統實際丟棄?鑑於沒有流量控制,這可以成爲緩衝區嗎? –