繁体   English   中英

UDP套接字上的sendto()不连贯行为

[英]sendto() incoherent behaviour on UDP socket

我在iOS上使用UDP套接字。 将其设置为非阻止模式和/或模拟不良连接时,我会遇到一个非常奇怪的行为。

要使用通常的fcntl将套接字设置为非阻塞模式:

fcntl(socketfd, F_SETFL, O_NONBLOCK);

为了模拟不良连接,我使用5/5输入/输出数据包丢失和50KBps输出限制的Network Link Conditionerer(在我的情况下,这保证了系统输出缓冲区在某个时候会变满)。

我使用sendto()发送数据,并使用clock()printf()为调用clock()


这是我的测试数据,以毫秒为单位:

  1. 阻塞,连接良好: min 0 / max 929 / avg 226 / 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()会在阻塞时返回错误,而不是从数据来看,调用似乎会阻塞,直到实际有执行它的空间为止

该行为似乎是相反的,但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无法保证将传送任何数据包,因此,由于任何原因,数据包路径上任何位置的任何软件或硬件都可以随时随意丢弃。

根据Wikipedia上UDP页面

UDP是RFC 768中记录的最小的面向消息的传输层协议。UDP 不保证上层协议进行消息传递 ,并且UDP层一旦发送便不保留UDP消息的状态。 因此,UDP有时被称为不可靠数据报协议。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM