An external controller sends a 120-byte message over a TCP / IP socket every 30 ms. The application receives these messages through the standard tcp / ip socket return function. It works fine under Linux and OSX (recv returns 120-byte messages every 30 ms). On Windows, recv returns a buffer of ~ 3500 bytes every 1 second. The rest of the time is returned 0. Wireshark under Windows shows messages that really go out every 30 ms.
How to make windows tcp socket work correctly (without delay)?
PS: I already played with TCP_NODELAY and TcpAckFrequency. Wireshark shows that everything is in order. Therefore, I believe that there are some Windows optimizations that should be disabled.
Reading -
int WMaster::DataRead(void) { if (!open_ok) return 0; if (!CheckSocket()) { PrintErrNo(); return 0; } iResult = recv(ConnectSocket, (char *)input_buff,sizeof(input_buff),0); nError=WSAGetLastError(); if(nError==0) return iResult; if(nError==WSAEWOULDBLOCK) return iResult; PrintErrNo(); return 0; }
Initialization -
ConnectSocket = INVALID_SOCKET; iResult = WSAStartup(MAKEWORD(2,2), &wsaData); ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ZeroMemory(&clientService, sizeof(clientService)); clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr( deviceName.toLatin1().constData() ); clientService.sin_port = htons( port); iResult = setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof (int)); u_long iMode=1; iResult=ioctlsocket(ConnectSocket,FIONBIO,&iMode); iResult = ::connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
CheckSocket -
bool WMaster::CheckSocket(void) { socklen_t len = sizeof (int); int retval = getsockopt (ConnectSocket, SOL_SOCKET, SO_ERROR, (char*)(&valopt), &len ); if (retval!=0) { open_ok=false; return false; }; return true; }
source share