我在iOS上使用UDP套接字。将其设置为非阻塞模式和/或模拟连接错误时,我会遇到一种非常奇怪的行为。
使用通常的fcntl
:
fcntl(socketfd, F_SETFL, O_NONBLOCK);
为了模拟连接不良,我使用网络链路条件,丢包率为5/5,输出限制为50KBps(在我的情况下保证系统输出缓冲区在某些时候会满了)。
我使用sendto()
发送数据,然后通过clock()
和printf()
拨打电话。
以下是我的测试数据,ms中的数据:
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))
答案 0 :(得分:2)
您如何知道系统的发送缓冲区已满?您只是假设因为您对连接进行了速率限制,数据会在发送缓冲区中备份。它更有可能在其他地方掉线。由于UDP不保证任何数据包将被传送,因此数据包路径上任何地方的任何软件或硬件都可以随时以任何理由随时丢弃。
UDP是一种面向消息的最小传输层协议 记录在RFC 768中。 UDP不保证上层 邮件传递协议,UDP层不保留任何状态 UDP消息一旦发送。因此,有时会引用UDP as 不可靠的数据报协议。