Advertisement

Recv timeout is 515.5ms bigger then I set

Started by November 13, 2016 04:35 AM
3 comments, last by Macin Software 8 years ago

Hi, I have problem with recv, but just on some computers. I have posted this thread somewhere else

because I have been thinking that it is a multithreading problem, but now after a lot more

information from debugging I know the exact place where it happens so I will put this one in

networking section better. Here in code, between check A2 and A3, is always exactly 515ms or 516ms,

EVEN THROUGH I set timeout with setsockopt as 1ms. It works on some comps, but some have problems and

give me this. I tried also to change timeout variable to something else, and it also does nothing -

it just adds that time to 515ms. I got rid of all another threads, so no - there is no switching to

something else. In this state it is a single-threaded app already. It happens on Acer Aspire One D250

(no extensions)+WinXP, and also it happens on virtual machine +Win7. I used also getsockopt to make

myself sure the timeout is written, and yes it is.

int myTcpSocket::XPrecieveMessage(string& message)
{
...stuff...
DWORD timeout = 1;
setsockopt(socketId, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

try
{printf("A%d\n",clock());
for(;;)
{printf("A2 %d\n",clock());
numBytes = recv(socketId,charMsg+received,1,0);printf("A3 %d\n",clock());
...stuff...
}printf("B%d\n",clock());
if(numBytes==6)
{...stuff...
}
}
catch(myException& excp)
{...stuff...
}
...stuff...
return msgSize;
}

1ms seems like a very short timeout. Perhaps you could use select first to make sure there's data before calling read?
Advertisement
setsockopt() can return an error code, and you don't appear to be checking it.

Are you sure you want to use this? According to this documentation

If a blocking receive call times out, the connection is in an indeterminate state and should be closed.


I'd second Nypyren's suggestion to look into select().
Typically, you will want to do one of a few things:

1) If you're using UDP, just call recvfrom(), either with blocking socket (if there is nothing else going on,) or with a non-blocking socket (if there are timers or whatnot.) In fact, a loop that calls recvfrom() for as long as it returns data, and then moves on to the rest of the main loop when there is no data, is ideal for a typical server game loop on top of UDP.
2) If you're using TCP, and have only a few sockets, you can do the same thing: Make the socket non-blocking, and call recv() until it has no data to return.
3) Otherwise, if you're using TCP with many socket, use select() (for up to about 60 sockets,) or use your favorite event-based socket poller (boost::asio, IO completion ports, etc.)

Looking at your code, it looks like you don't really want the timeout of 1 millisecond anyway; instead you want the non-blocking socket behavior: https://msdn.microsoft.com/en-us/library/windows/desktop/ms738573(v=vs.85).aspx

Finally, when I see this code, I think that you may not realize that TCP sockets will not receive what you send "1 for 1" in blocks -- if you send first 4 bytes, and then 11 bytes, then the other end may receive 4 and 11 bytes, or just 15 bytes, or 1 byte, 1 byte, 1 byte, ... or any other combination of the 15 bytes you sent.

if(numBytes==6)
[/quote]

Typically, you will want to test for "numBytes >= (needed)" instead, and then remove the bytes you processed from the incoming buffer, keeping the rest.
(I can tell you're using TCP, because you use recv(), rather than recvfrom().)
enum Bool { True, False, FileNotFound };

I put select before recv and dumped setsockopt and it works OK. Thanks!

This topic is closed to new replies.

Advertisement