Advertisement

Problem recv()ing Packets

Started by July 05, 2006 12:51 PM
2 comments, last by Kylotan 18 years, 7 months ago
Off the bat I will admit that I am new to network programming. I am having trouble sending and recieving game data with TCP packets. With just strings (text), I am able to send and recieve in my game fine, so I know the connections are working. My problem though is trying to send and recieve multiple kinds of data. Right now I have three, the server sends the client its ID on connection. I also am trying to support in game chat and update the position of the players. My approach was this, make the first character in the buffer a code letting the client know what kind of data its going to get. After that I just stored the data. Here is my code, as it is now it thinks location packets are text, and prints out a lot of junk to my edit control. Sorry if the code is a little messy:

//how my location packets are sent
int CMultiPlayer::SendLocation()
{
	int buftracker = 0;
	char buf[29];
	buf[buftracker] = 1;
	buftracker++;
	char conversionchar[4];
	memcpy((void*)conversionchar,(void*)&ClientID,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	memcpy((void*)conversionchar,(void*)&m_Player->m_vPlayer.x,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	memcpy((void*)conversionchar,(void*)&m_Player->m_vPlayer.y,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	memcpy((void*)conversionchar,(void*)&m_Player->m_vPlayer.z,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	memcpy((void*)conversionchar,(void*)&m_Player->m_vPlayerLook.x,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	memcpy((void*)conversionchar,(void*)&m_Player->m_vPlayerLook.y,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	memcpy((void*)conversionchar,(void*)&m_Player->m_vPlayerLook.z,4);
	for (int i = 0; i < 4; i++){buf[buftracker] = conversionchar;buftracker++;}
	int Size = 29;
	sendall(theSocket,buf,&Size);
	return 0;
}

int CMultiPlayer::GetInfoFromServer()
{
	//static int Counter = 0;
	//static char FullPacket[256];
	//static bool NeedAnotherRound = false;
	static char incommingbuffer[512];
	static int Tracker = 0;
	static int PacketSize = 0;
	char buffer[256];
	for (int i = 0; i < 256; i++)
		buffer = 0;
	int retval = 0;
	
	retval = recv(theSocket,buffer,sizeof(buffer),0);
	if (retval == -1 || retval == 0) return 0;
	
	for (int i = 0; i < retval; i++)
	{
		incommingbuffer[Tracker] = buffer;
		Tracker++;
	}

	if (incommingbuffer[0] == 0)
		PacketSize = 256;
	else if (incommingbuffer[0] == 1)
		PacketSize = 29;
	else if (incommingbuffer[0] == 2)
		PacketSize = 5;

	//packet done
	if (Tracker >= PacketSize)
	{
		//transfer to buffer, snug up incommingbuffer, decrease tracker by packetsize, break
		for (int i = 0; i < PacketSize; i++)
			buffer = incommingbuffer;
		int TrackerTwo = PacketSize;
		if (PacketSize != Tracker)
		{
			for (int i = 0; i < 512; i++)
			{
				incommingbuffer = incommingbuffer[TrackerTwo];
				TrackerTwo++;
				if (TrackerTwo >= Tracker)
					break;
			}
		}
		Tracker -= PacketSize;
	}
	else
	{
		OutputDebugString("Incomplete Packet\n");
		return 0;
	}
	
	//text 256
	if (buffer[0] == 0)
	{
		OutputDebugString("Text Recieved\n");
		char String[256];
		for (int i = 0; i < 255; i++)
			String = buffer[i+1];
		String[255] = 0;
		sprintf(ActionText[CurrentArray],String);
		if (CurrentArray != 3)
			CurrentArray++;
	}
	//location 29
	else if (buffer[0] == 1)
	{
		OutputDebugString("Location Recieved\n");
		int buftracker = 1;
		char buf[4];
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&ClientID,(void*)buf,4);
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&m_NPlayer.m_vPlayer.x,(void*)buf,4);
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&m_NPlayer.m_vPlayer.y,(void*)buf,4);
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&m_NPlayer.m_vPlayer.z,(void*)buf,4);
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&m_NPlayer.m_vPlayerLook.x,(void*)buf,4);
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&m_NPlayer.m_vPlayerLook.y,(void*)buf,4);
		for (int i = 0; i < 4; i++){buf = buffer[buftracker]; buftracker++;}
		memcpy((void*)&m_NPlayer.m_vPlayerLook.z,(void*)buf,4);
	}
	//client 5
	else if (buffer[0] == 2)
	{
		OutputDebugString("Client Info Recieved\n");
		int ClientNumber;
		char buf[4];
		buf[0] = buffer[1];
		buf[1] = buffer[2];
		buf[2] = buffer[3];
		buf[3] = buffer[4];
		memcpy((void*)&ClientNumber,(void*)buf,4);
	}
        return 0;
}

I'm at a loss for what the problem is. If anyone has any ideas I would appreciate it very much. Thank you, Dev578
I can't answer your question, but remember TCP doesn't deal in packets! It sends a stream of data. So you must be ready to pick up data half-way through a 'packet'. It might be easier to see the problem if the code was a bit cleaner; some of that buffer shuffling looks a little superfluous, and you could certainly do it with memcpy instead, I think. Are you sure sendall is doing the right thing? I don't see the code for it there, and I don't recognise it as standard either.
Advertisement
Sorry, forgot to post sendall, but tests show that it is doing what it is supposed to. In GetInfoFromServer(), I output everything that was recieved as text, and it was recieving everyting. My problem is that it is not routing it to the correct area to be processed (text, position, or client). If I stop the server from sending the clients position data, the text works fine. With the server sending position data, it is able to correctly send the client information and then one position 'packet.' Then the rest of the position packets get processed as text. Well, I think I have at least narrowed down my problem to the routing of the data, but I keep looking over the code and I don't see where it is going wrong.

Dev578
So really, what you're saying is that it's not a networking problem, right? If all the data is arriving at the other side then the problem is not really anything to do with recv().

On your second iteration, you copy the received packet into the 2nd half of incomingbuffer. But when you copy back into buffer, you're copying from the 1st half of incomingbuffer. Who knows what it ends up with.

You should be able to step through this with a debugger. Or just output some of the data in the buffers as you see it.

Also, you need to work with the amount of data it tells you that you received, and not assume you received X amount of bytes based on the first byte you read. The first byte you read might not even be your packet-type field; it could be part of a previous 'packet' that you didn't get the last time. This is what is meant about TCP not dealing in packets - you have no guarantee that the data will arrive in the same sized blocks that they're sent in. Your code should be able to accommodate the legal-but-unlikely event that you get your data back in one byte per recv call.

This topic is closed to new replies.

Advertisement