I've been stabbing at this problem for months now, and I still can't figure it out.
Whenver someone goes up and down a staircase in my game in rapid succession, their TCPBuffer gets a few bytes zeroed which causes one of three fatal exceptions.
It can't (can) be the server because I noticed during one crash, the 'short' datatype in the TCPBuffer that represented the size of the packet that was being readin was zero (No matter how badly the data on the server is, the packet size constant will never be zero!).
I've outputted all the sizes of packets the client read in before the crash, and they were all normal values (eg.. its not the case of the server sending a packet with the wrong size, thus causing the shiftTCPBuffer() function to go hay-wire on the buffer).
The client's sShiftTCPBuffer command looks like this (Where TheStackSize = constant int = 1000).
public void sShiftTCPBuffer()
{
/*
* Name: sShiftTCPBuffer
* Programmer: Peter Blain.
* Version: January 7, 2006.
* Description: This procedure shifts the user's TCP buffer back by a specified number
* bytes; for use with reading packets.
*/
/* Get the number of bytes that the buffer needs to be shifted. */
short TheNumberOfBytes = BitConverter.ToInt16(TheTCPBuffer, 1);
TheDisplay += TheNumberOfBytes.ToString() + "\n";
/* Shift and clear the TCP stack. */
Array.Copy(TheTCPBuffer, TheNumberOfBytes,
TheTCPBuffer, 0, TheTCPStackSize - TheNumberOfBytes);
Array.Clear(TheTCPBuffer, (TheTCPStackSize - 1) - TheNumberOfBytes, TheNumberOfBytes);
/* Now decrement the TCP stack. */
TheTCPOffset -= TheNumberOfBytes;
if (BitConverter.ToInt16(TheTCPBuffer, 1) == 0 &&
TheTCPOffset >= 3) throw new Exception("!??!?!333");
}
The server's send packet function looks like this..
public void sSendPacket(byte[] TheData, int TheClient)
{
/*
* Name: sSendPacket
* Programmer: Peter Blain.
* Version: Janurary 7, 2006.
* Description: This procedure sends the given data packet to the specified client, via
* its connection.
*/
MyPlayerStats[TheClient].ThePacketsSent++;
try
{
if (TheClients[TheClient].MySocket.Send(TheData, 0, TheData.Length, SocketFlags.None) !=
TheData.Length)
{
throw new Exception("Could not send all data to user.");
}
}
catch (SocketException)
{
sDisconnect(TheClient, null);
}
}
.. and no.. sDisconnect() doesn't get called during a crash. The error is in the client itself.
The client's recieve command.
public void sCheckReceive()
{
/*
* Name: sCheckReceive
* Programmer: Peter Blain.
* Version: July 17, 2006.
* Description: This procedure checks if there is data coming from the socket. If so
* it recieves the data and then calls a check for complete packets.
*/
try
{
if (MyGlobalSocket.Poll(0, SelectMode.SelectRead))
{
int TheBytesRead = MyGlobalSocket.Receive(TheTCPBuffer, TheTCPOffset, TheTCPStackSize - TheTCPOffset, SocketFlags.None);
/* Increment the TCP offset. */
TheTCPOffset += TheBytesRead;
/* Before starting the recieve function again, lets check if we have any
* complete packets. */
sCheckForCompletePackets();
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Fleurin - Socket Recieve error.");
Application.Exit();
}
}
and lastly... the check for complete packets().
public void sCheckForCompletePackets()
{
/*
* Name: sCheckForCompletePacket
* Programmer: Peter Blain.
* Version: January 6, 2006.
* Description: This procedure checks if a complete packet has been recieved.
*/
while (TheTCPOffset >= 3)
{
/* Check if the size of the packet being recieved has been
* completly recieved. */
short ThePacketSize = BitConverter.ToInt16(TheTCPBuffer, 1);
if (ThePacketSize == 0) throw new Exception("!?!?!?!");
if (TheTCPOffset >= ThePacketSize)
{
switch (TheTCPBuffer[0])
{
/* Packet: User is requesting to spawn. */
case (byte)FleurinFlags.EServerSend.SpawnPacket:
sPakReadSpawn();
sShiftTCPBuffer();
TheProgramLocation = EProgramLocation.InGame;
break;
case (byte)FleurinFlags.EServerSend.PopUp:
sPakReadPopUp();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Inventory:
sPakReadInventory();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Movement:
sPakReadMovement();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Player:
sPakReadPlayer();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Costume:
sPakReadCostume();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Message:
sPakReadMessage();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Direction:
sPakReadDirection();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Flush:
sPakReadFlush();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Monster:
sPakReadMonster();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.PoofEffect:
sPakReadPoof();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.NumberEffect:
sPakReadXP();
sShiftTCPBuffer();
break;
case(byte)FleurinFlags.EServerSend.Health:
sPakReadHealth();
sShiftTCPBuffer();
break;
case(byte)FleurinFlags.EServerSend.Item:
sPakReadItem();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Skill:
sPakReadSkill();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Spell:
sPakReadSpell();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Mana:
sPakReadMana();
sShiftTCPBuffer();
break;
case (byte)FleurinFlags.EServerSend.Projectile:
sPakReadProjectile();
sShiftTCPBuffer();
break;
/* Packet: Corrupted. */
default:
throw new Exception("Corrupted TCP buffer detected; you've been dictated out.");
}
}
else
{ break; }
}
}
HALP! [depressed]