If the server sends 2 items of data at almost the same time, the client receives the 2nd item of data. It will have about 75% to receive garbage.
I'm pretty sure the problem is in the C# client:
- I've printed the buffer in the server - everything is correct
- Used Wireshark to check the buffer - everything is correct
- And used Python to receive the data instead of using C# - seems to be correct
I tried:
- Clear the buffer when receiving - nothing happened
- Adding a delay before the receive functions - it worked. But I'm not sure how long I should wait. And because of the probability of getting the correct data, it might not be the correct way to fix this. Also, as a game I want to receive data as quickly as it can.
This is the code about network in the client:
(This client uses GODOT - I've deleted parts of the code that isn't about receiving data)
public partial class Network : Node
{
public bool error = false; // Happened Error.
private Socket socket = null; // The Socket File.
private Change change = new Change(); // The Changer To Change Packages And Bytes.
private byte[] buffer = new byte[64]; // The Buffer.
private List<Tuple<object, PackageType>> packageGet = new List<Tuple<object, PackageType>>(); // The Packages Got And Not Handled.
public override void _ExitTree()
{
close();
}
public override void _Process(double delta) //
{
if (!updated && packageGet.Count > 0)
{
handleEvent();
}
}
/**
* @brief Connect To The Server.
* @param ipParameter The IP Address.
* @return The Result.
*/
public bool connect(string ipParameter)
{
close();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
if (!socket.ConnectAsync(ipParameter, 10000).Wait(ConfigPanel.connectTime))
{
return false;
}
}
catch
{
return false;
}
startRead();
return true;
}
/**
* @brief Close The Socket.
*/
public void close()
{
if (socket != null && socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
/**
* @breif Start To Read Data From Server.
*/
private void startRead()
{
Array.Clear(buffer, 0, buffer.Length);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, read, null);
}
/**
* @breif Read Data Got (Callback From startRead()).
* @param resultParameter The Result.
*/
private void read(IAsyncResult resultParameter)
{
try
{
if (!socket.Connected || socket == null)
{
return;
}
int length = socket.EndReceive(resultParameter);
if (length == 0)
{
close();
// Error
return;
}
PackageType type = PackageType.None;
object package = change.toPackage(buffer, ref type);
packageGet.Add(new Tuple<object, PackageType>(package, type));
startRead();
}
catch
{
// Error
}
}
/**
* @brief Handle The Events.
*/
private void handleEvent()
{
// Just Handle
}
}
Sorry for the bad indentation :(, Thanks for helping.
TCP is a streaming protocol, not a message protocol; when calling
Read/Receive/etc:as such, you need to a: respect
length, and b: implement some kind of framing protocol; usually this means something like "the first 4 bytes of any message are the length, in little-endian int32, of the message that follows", so: you'd buffer at least 4 bytes (possibly over 4 receive calls, although in reality: usually 1), parse the length, then buffer at least that many bytes (possibly over many receive calls), and then parse the message. If you have over-read (i.e. in the "at least", you consumed more): then you need to retain that backlog too.Honestly, it is easier to use the "pipelines" model, which simplifies all this buffer management; there's a 3-and-a-bit series of mine here on that topic, although it is quite a paradigm shift.