Merge pull request #206 from NPrincen/develop
Minimize Send and Receive Socket Timeout Delays
This commit is contained in:
@@ -117,13 +117,16 @@ XPCSocket aopenUDP(const char *xpIP, unsigned short xpPort, unsigned short port)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Set timeout to 100ms
|
||||
// Set socket timeout period for sendUDP to 1 millisecond
|
||||
// Without this, playback may become choppy due to process blocking
|
||||
#ifdef _WIN32
|
||||
DWORD timeout = 100;
|
||||
// Minimum socket timeout in Windows is 1 millisecond (0 makes it blocking)
|
||||
DWORD timeout = 1;
|
||||
#else
|
||||
// Set socket timeout to 1 millisecond = 1,000 microseconds to make it the same as Windows (0 makes it blocking)
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 250000;
|
||||
timeout.tv_usec = 1000;
|
||||
#endif
|
||||
if (setsockopt(sock.sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0)
|
||||
{
|
||||
@@ -188,13 +191,13 @@ int sendUDP(XPCSocket sock, char buffer[], int len)
|
||||
/// \returns If an error occurs, a negative number. Otherwise, the number of bytes read.
|
||||
int readUDP(XPCSocket sock, char buffer[], int len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Windows readUDP needs the select command- minimum timeout is 1ms.
|
||||
// Without this playback becomes choppy
|
||||
// For readUDP, 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;
|
||||
FD_SET stExceptFDS;
|
||||
fd_set stReadFDS;
|
||||
fd_set stExceptFDS;
|
||||
struct timeval timeout;
|
||||
|
||||
// Setup for Select
|
||||
FD_ZERO(&stReadFDS);
|
||||
@@ -202,12 +205,13 @@ int readUDP(XPCSocket sock, char buffer[], int len)
|
||||
FD_ZERO(&stExceptFDS);
|
||||
FD_SET(sock.sock, &stExceptFDS);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100000;
|
||||
// Set timeout period for select to 0.05 sec = 50 milliseconds = 50,000 microseconds (0 makes it polling)
|
||||
// TO DO - This could be set to 0 if a message handling system were implemented, like in the plugin.
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 50000;
|
||||
|
||||
// Select Command
|
||||
int status = select(-1, &stReadFDS, (FD_SET*)0, &stExceptFDS, &tv);
|
||||
int status = select(sock.sock+1, &stReadFDS, NULL, &stExceptFDS, &timeout);
|
||||
if (status < 0)
|
||||
{
|
||||
printError("readUDP", "Select command error");
|
||||
@@ -218,11 +222,9 @@ int readUDP(XPCSocket sock, char buffer[], int len)
|
||||
// No data
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If no error: Read Data
|
||||
status = recv(sock.sock, buffer, len, 0);
|
||||
#else
|
||||
// For apple or linux-just read - will timeout in 0.5 ms
|
||||
int status = (int)recv(sock.sock, buffer, len, 0);
|
||||
#endif
|
||||
if (status < 0)
|
||||
{
|
||||
printError("readUDP", "Error reading socket");
|
||||
|
||||
@@ -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,43 +90,54 @@ 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;
|
||||
FD_SET stExceptFDS;
|
||||
timeval tv;
|
||||
fd_set stReadFDS;
|
||||
fd_set stExceptFDS;
|
||||
struct timeval timeout;
|
||||
|
||||
// Setup for Select
|
||||
FD_ZERO(&stReadFDS);
|
||||
FD_SET(sock, &stReadFDS);
|
||||
FD_ZERO(&stExceptFDS);
|
||||
FD_SET(sock, &stExceptFDS);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 250;
|
||||
|
||||
// Set timeout period for select to 0 to poll the socket
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
// Select Command
|
||||
int result = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv);
|
||||
if (result == SOCKET_ERROR)
|
||||
int status = select(sock+1, &stReadFDS, NULL, &stExceptFDS, &timeout);
|
||||
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 (status == 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user