【发布时间】:2016-12-27 11:36:26
【问题描述】:
我在 iOS 上使用 UDP 套接字。将其设置为非阻塞模式和/或模拟不良连接时,我遇到了一种非常奇怪的行为。
使用通常的fcntl 将套接字设置为非阻塞模式:
fcntl(socketfd, F_SETFL, O_NONBLOCK);
为了模拟不良连接,我使用了具有 5/5 输入/输出数据包丢失和 50KBps 输出限制的 Network Link Conditioneer(在我的情况下,这可以保证系统输出缓冲区在某些时候会被填满)。
我使用sendto() 发送数据,并使用clock() 和printf() 为通话计时。
这是我测试的数据,以毫秒为单位:
- 阻塞,连接良好:
min 0/max 929/avg 226/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()在阻塞时返回错误,而不是从数据来看,调用似乎会阻塞,直到有实际空间来执行它
这种行为似乎颠倒了,除了 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))
【问题讨论】: