Rulk
Rulk

Reputation: 41

Nonblocking Winsockets c++ strange delays

I'm porting online game from Linux to windows. On Linux everything works great, but on windows I have some strange behavior. Client and server communicate through constant TCP connection. Server sends packet every 0.5 second. And on Linux I receive packet every 0.5 second, but on windows I have something like this:0.9,0.3,0.3,0.3,0.9 and so on(The interval actually depend on the ping to the server interval may be something like 0.7,0.2,0.7). I use non-blocking sockets. I tried disabling tcp nagle algorithm.

Here is some client's code:

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int iStatus = getaddrinfo(Settings->GetDnSAddr().c_str(),
 Settings->GetPortStr().c_str(), &hints, &servinfo);
if(iStatus != 0 || servinfo == NULL)
{
    iState = L_CONNECT_DOWN;
    throw ExeptionNetwork(903,__FILE__,__LINE__,iStatus);
    return 0;
}

iSocketFD = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol);
if (iSocketFD == INVALID_SOCKET)
{
    THROWNETWORK(901);
}

cout<<"Connecting to server:"<<Settings->GetIPv4Addr()<<":"<<Settings->GetPort()<<endl;
if (connect(iSocketFD,servinfo->ai_addr,servinfo->ai_addrlen) == SOCKET_ERROR)
{
    cout<<"Connection failed:"<<errno<<endl;
    iState = L_CONNECT_DOWN;
    THROWNETWORK(902);
    return 0;
}
cout<<"Connected"<<endl;

#if (defined WIN32)||(defined WINCE)
unsigned long iMode = 1;
if (SOCKET_ERROR == ioctlsocket(iSocketFD, FIONBIO, &iMode))
{
    THROWNETWORK(903);
}
#else
fcntl(iSocketFD, F_SETFL, O_NONBLOCK);
#endif


char flag =1;
setsockopt(iSocketFD, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));

Then to read i peek with recv() and if there is something to read i read.

Any Ideas? May be It be somehow connected to calling recv to often? I'm thinking about separating network code to the separate thread maybe it will help...

Upvotes: 0

Views: 274

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598134

When working with non-blocking sockets, don't use recv() to peek bytes looking for data. Use select(), WSAAsyncSelect(), or WSAAsyncEvent() to be notified when data becomes available, then call recv() to read it.

Upvotes: 2

Related Questions