Click to See Complete Forum and Search --> : Mother of all Networking Problems (involves MSG_PEEK probably)


Timmmm3d
May 8th, 2003, 01:02 PM
OK, here's the situation. I have a game (client-server) which works in linux, but when I try and run it in windows, the networking bit doesn't work.

The specific bit, is in the server (although the client probably doesn't work either, but they are coded symetrically, so I can fix that later). Anyway, the server has a TCP socket - called TCPSocket - which it wants to receive packets on. (I know they definately *are* send correctly).

The packets come as 2 bytes containing the packet length, and the length bytes containing the packet. Here is the code I use to receive it (the socket is non-blocking):


uint16 Length;
int R;
R = recv(TCPSocket, reinterpret_cast<char*>(&Length), 2, MSG_PEEK | MSG_NOSIGNAL | MSG_DONTWAIT);
if (R == 0)
{
throw TException("Client::RecvPacket", "recv() returned 0.", "Connection closed.", "NET_ERROR");
}
else if (R == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
{
cout << WSAGetLastError() << endl;
throw TException("Client::RecvPacket", "recv() returned SOCKET_ERROR.", "Connection closed.", "NET_ERROR");
}
else if (R == 2)
{
cout << "Got Length\n";
char* Buffer = new char[Length + 2];
R = recv(TCPSocket, Buffer, Length + 2, MSG_PEEK | MSG_NOSIGNAL | MSG_DONTWAIT);
if (R == 0)
{
delete[] Buffer;
throw TException("Client::RecvPacket::", "recv() returned 0.", "Connection closed.", "NET_ERROR");
}
else if (R == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
{
delete[] Buffer;
cout << WSAGetLastError() << endl;
throw TException("Client::RecvPacket", "::recv() returned SOCKET_ERROR.", "Connection closed.", "NET_ERROR");
}
else if (R == Length + 2)
{
recv(TCPSocket, Buffer, Length + 2, MSG_WAITALL | MSG_NOSIGNAL);
TNetwork::Packet P(Buffer + 2, Length);
delete[] Buffer;
return P;
}
else
{
cout << "Only received " << R << " so far. Need " << Length + 2 << endl;
}
delete[] Buffer;
}
else
{
cout << "Only received " << R << " byte of length so far. Need 2\n";
}


Oh yeah, also, 2 bytes containing a UDP port number are exchaned first. That bit works.
After that, the first length it receives it 20 (which is correct), but then the second recv(...PEEK) only ever says there are the 2 bytes of the length available. If I scrap all that and receive bytes one at a time, however, I get them all!

Seems, MSG_PEEK doesn't work properly (or as expected).

Any help anyone.

Thankyou for you time :)

Tim Hutt.

TekBoy
May 9th, 2003, 12:18 PM
the flags MSG_DONTWAIT and MSG_WAITALL are unknown to me and are not used in Windows Sockets, as far as I can tell. At least they are undocumented in Microsoft's version of recv().

Is my assumption correct that these two flags are POSIX? Is one for a blocking call and one for a non-blocking one?

I think that the reason why recv() always only returns two bytes, is that it is a non-blocking call, beause the MSG_WAITALL flag is ignored by Windows Sockets. In Windows Sockets, you must explicitly switch the socket between blocking and non-blocking mode, you cannot simply specify this mode as a parameter to recv().