gpt4 book ai didi

c++ - 为什么 Windows udp 接收套接字的超时总是比 SO_RCVTIMEO 设置的长 500 毫秒?

转载 作者:太空狗 更新时间:2023-10-29 23:12:13 27 4
gpt4 key购买 nike

易于重现,这是我正在做的伪代码:

  1. 设置UDP套接字
  2. 将超时设置为一个值(Timeout set)
  3. 检查我设置的超时时间(Timeout checked)
  4. 尝试在该套接字上接收(当没有流量时)。
  5. Time 超时需要多长时间。 (超时前的时间)

当我这样做时,我得到以下输出:

Timeout set: 0.1s | Timeout checked: 0.1s | Time until timeout: 0.6s | difference: 0.5s
Timeout set: 0.2s | Timeout checked: 0.2s | Time until timeout: 0.7s | difference: 0.5s
Timeout set: 0.4s | Timeout checked: 0.4s | Time until timeout: 0.9s | difference: 0.5s
Timeout set: 0.8s | Timeout checked: 0.8s | Time until timeout: 1.3s | difference: 0.5s
Timeout set: 1.6s | Timeout checked: 1.6s | Time until timeout: 2.1s | difference: 0.5s
Timeout set: 3.2s | Timeout checked: 3.2s | Time until timeout: 3.7s | difference: 0.5s

为什么windows udp socket超时总是比setsockopt中设置的长500ms?

查看setsockopt here在涉及 SO_RCVTIMEO 的部分下,我看不到有关为什么会发生这种情况的信息。


重现代码:

#include "stdafx.h"
#include "winsock2.h"
#include <chrono>
#include <iostream>

int main() {
WORD wVersionRequested;
WSADATA wsaData;

wVersionRequested = MAKEWORD(2, 2);
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
while (true);
}

sockaddr_in socketAddress = { 0 };
socketAddress.sin_family = PF_INET;
socketAddress.sin_port = htons(1010);
socketAddress.sin_addr.s_addr = INADDR_ANY;

// Create the socket
SOCKET mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!mSocket) {
printf("Socket failed with error code : %d", WSAGetLastError());
while (true);
}

//Bind
if (bind(mSocket, (struct sockaddr *)&socketAddress, sizeof(socketAddress)) == SOCKET_ERROR) {
printf("Bind failed with error code : %d", WSAGetLastError());
while (true);
}

// Receive nothing over several different set timeouts
for (double timeout = 0.1; timeout < 4.0; timeout *= 2) {

// Set timeout
DWORD lBuffer[2] = { 0, 0 };
int lSize;
lBuffer[0] = static_cast<DWORD>(1000.0 * timeout);
lSize = sizeof(DWORD);
if (setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)lBuffer, lSize) != 0) {
printf("Set socket option failed with error code : %d", WSAGetLastError());
while (true);
}

// Check that we get what we set.
DWORD lBufferout[2] = { 0, 0 };
if (getsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)lBufferout, &lSize) != 0) {
printf("Set socket option failed with error code : %d", WSAGetLastError());
while (true);
}

// Receive and time
char buffer[50];
sockaddr_in senderAddr;
int senderAddrSize = sizeof(senderAddr);

auto s = std::chrono::steady_clock::now();

int transferred = recvfrom(mSocket, (char*)buffer, 50, 0,
(sockaddr*)&senderAddr, &senderAddrSize);

auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - s).count() / 1000.0;

std::cout << "Timeout set: " << timeout << "s | Timeout checked: " << lBufferout[0] / 1000.0 << "s | Time until timeout: " << duration << "s | difference: " << duration - timeout << "s\n";
}

while (true);

return 0;
}

注意:此代码预计端口 1010 上没有流量。如果不是这种情况,请更改该数字。

最佳答案

据说here:

There is an undocumented minimum limit of about 500mS on SO_RCVTIMEO.

这很可能是通过始终将 500 毫秒添加到为 SO_RCVTIMEO 设置的任何值来实现的。

关于c++ - 为什么 Windows udp 接收套接字的超时总是比 SO_RCVTIMEO 设置的长 500 毫秒?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48054568/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com