Minimize SendTo and Read Socket Timeout Delays

SendTo and Read were using longer than necessary socket timeouts that may add to process time delay and stuttering.  They were also using different values between Window and Linux/Mac.  The timeouts are now standardized for all versions and coded in the same manner as the xplaneConnect.c functions.
This commit is contained in:
Norman Princen
2020-05-12 10:25:01 -07:00
committed by GitHub
parent 581675818b
commit d2486dd73b

View File

@@ -56,22 +56,25 @@ namespace XPC
return;
}
// Set Timout
int usTimeOut = 500;
// Set timeout period for SendTo to 1 millisecond
// Without this, playback may become choppy due to process blocking
#ifdef _WIN32
DWORD msTimeOutWin = 1; // Minimum socket timeout in Windows is 1ms
if(setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&msTimeOutWin, sizeof(msTimeOutWin)) != 0)
// Minimum socket timeout in Windows is 1 millisecond (0 makes it blocking)
DWORD timeout = 1;
#else
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 1000;
#endif
if (setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0)
{
#ifdef _WIN32
int err = WSAGetLastError();
Log::FormatLine(LOG_ERROR, tag, "ERROR: Failed to set timeout. (Error code %i)", err);
}
#else
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = usTimeOut;
setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
Log::WriteLine(LOG_ERROR, tag, "ERROR: Failed to set timeout.");
#endif
}
}
UDPSocket::~UDPSocket()
@@ -87,11 +90,9 @@ namespace XPC
int UDPSocket::Read(unsigned char* dst, int maxLen, sockaddr* recvAddr) const
{
socklen_t recvaddrlen = sizeof(*recvAddr);
int status = 0;
#ifdef _WIN32
// Windows readUDP needs the select command- minimum timeout is 1ms.
// Without this playback becomes choppy
// For Read, use the select command - minimum timeout of 0 makes it polling.
// Without this, playback may become choppy due to process blocking
// Definitions
FD_SET stReadFDS;
@@ -103,27 +104,40 @@ namespace XPC
FD_SET(sock, &stReadFDS);
FD_ZERO(&stExceptFDS);
FD_SET(sock, &stExceptFDS);
// Set timeout period for select to 0 to poll the socket
tv.tv_sec = 0;
tv.tv_usec = 250;
tv.tv_usec = 0;
// Select Command
int result = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv);
if (result == SOCKET_ERROR)
int status = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv);
if (status < 0)
{
#ifdef _WIN32
int err = WSAGetLastError();
Log::FormatLine(LOG_ERROR, tag, "ERROR: Select failed. (Error code %i)", err);
#else
Log::WriteLine(LOG_ERROR, tag, "ERROR: Select failed.");
#endif
return -1;
}
if (result <= 0) // No Data or error
if (result == 0)
{
// No data
return -1;
}
// If no error: Read Data
status = recvfrom(sock, (char*)dst, maxLen, 0, recvAddr, &recvaddrlen);
if (status < 0)
{
#ifdef _WIN32
int err = WSAGetLastError();
Log::FormatLine(LOG_ERROR, tag, "ERROR: Receive failed. (Error code %i)", err);
#else
// For apple or linux-just read - will timeout in 0.5 ms
status = (int)recvfrom(sock, dst, 5000, 0, recvAddr, &recvaddrlen);
Log::WriteLine(LOG_ERROR, tag, "ERROR: Receive failed.");
#endif
}
return status;
}