83725

Why is the timeout on a windows udp receive socket always 500ms longer than set by SO_RCVTIMEO?

Easy to reproduce, here is the psuedo code of what i am doing:

<ol> <li>Set up a UDP socket</li> <li>Set the timeout to a value (Timeout set)</li> <li>Check the timeout that I set (Timeout checked)</li> <li>Attempt to receive on that socket (when there is no traffic). </li> <li>Time how long it takes to timeout. (Time until Timeout)</li> </ol>

When I do this i get the following output:

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

<strong>Why does the windows udp socket timeout always run 500ms longer than that set in setsockopt?</strong>

Looking at setsockopt here I can see no information about why this is occurring under the sections involving SO_RCVTIMEO.

<hr>

Code to reproduce:

#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; }

Note: This code is expecting there to be no traffic on port 1010. If this is not the case, change that number.

Answer1:

It is stated here:

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

It is likely that this is implemented by always adding 500ms to any value set for SO_RCVTIMEO.

Recommend

  • How to print formatted date in F#
  • Creating a batch file to delete multiple, separated subdirectories
  • Send email from Outlook Express in C#
  • Find if N strings are anagrams of each other
  • How to configuring NTL library in Visual Studio 2017
  • Using forward declarations for built in datatypes
  • Precompiled header and Visual Studio
  • ERROR LNK2019:unresolved external symbol, c++ [duplicate]
  • Any good way for getting a single instance instead of using Singleton (in C#)
  • Assign even odd page numbers in word
  • Read certain key from certain section of ini file (sed/awk ?)
  • jquery add an event handler to objects in an array
  • Count the occurrences across multiple columns
  • How do I fix “The program issued a command but the command length is incorrect.” error when calling
  • iOS custom UTI in UIDocumentPickerViewController initWithDocumentTypes
  • CRASH: *** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 9]
  • Is there any purpose for h2-h6 headings in HTML5?
  • get path to groovy source file at runtime
  • git add error : “fatal : malloc, out of memory”
  • npm 5.4.1 install/uninstall all failing
  • Bash if statement with multiple conditions
  • how to upload multiple files in c# windows application
  • presentShareDialogWithParams posts to FB wall, but callback handler results say error
  • Ionic 2 storage is not cleaning up on uninstall - Only for signed APK
  • $wpdb not working in file of WordPress plugin
  • Meteor helpers not available in Angular template
  • Lost migrations and Azure database is now out of sync
  • C# - Serializing and deserializing static member
  • Sony Xperia Z Tablet not found by adb
  • How would I use PHP exceptions to define a redirect?
  • DirectX11 ClearRenderTargetViewback with transparent buffer?
  • Javascript convert timezone issue
  • Web-crawler for facebook in python
  • Unit Testing MVC Web Application in Visual Studio and Problem with QTAgent
  • Buffer size for converting unsigned long to string
  • Hits per day in Google Big Query
  • How do you join a server to an Active Directory (domain)?
  • How to get Windows thread pool to call class member function?
  • How can I remove ASP.NET Designer.cs files?
  • java string with new operator and a literal