Reputation: 345
I send 2 successive packets from my client to the server who is listening using BeginReceive
The server always receives the first packet but not the other EXCEPT if I run the client in debug mode and slowly send the next packet after the other.
Here's a snippet from my sending function
if (soc.Connected)
{
byte[] byData = new byte[System.Text.Encoding.ASCII.GetByteCount("Hi")];
byData = System.Text.Encoding.ASCII.GetBytes("Hi");
soc.Send(BitConverter.GetBytes(byData.Length));
soc.Send(byData);
}
And here's is my call back function located inside of my server:
private void Recieve(IAsyncResult iar)
{
int j = 0;
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndReceive(iar);
if (!SocketConnected(server_conn))
{
server_conn.Close();
return;
}
if (g_bmsg.Length != 0)
{
logthis(server_conn.RemoteEndPoint.ToString() + ": " + Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
}
//Find out who sent this
foreach (ClientData cls in clientlist)
{
if (server_conn.RemoteEndPoint == cls.clientsock.RemoteEndPoint)
{
j = cls.index;
break;
}
}
server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), server_conn);
}
Upvotes: 2
Views: 2160
Reputation: 51224
When working with TCP/IP sockets (or pretty much any communication layer), you rarely have a guarantee that the entire message you intended to send will come in a single packet.
This means that you should always keep a FIFO buffer of your own, and parse it sequentially.
This is the general idea:
// fifo queue (for background thread parsing, make sure it's thread safe)
private readonly ConcurrentQueue<byte> _commQueue = new ConcurrentQueue<byte>();
In your Receive
method, you should simply enqueue the data to the FIFO:
private void Receive(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
// check how many bytes we actually received
var numBytesReceived = server_conn.EndReceive(iar);
if (!SocketConnected(server_conn))
{
server_conn.Close();
return;
}
// get the received data from the buffer
if (numBytesReceived > 0)
{
for (int i = 0; i < numBytesReceived; i++)
_commQueue.Enqueue(g_bmsg[i]);
// signal the parser to continue parsing
NotifyNewDataReceived();
}
// continue receiving
server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), server_conn);
}
Upvotes: 1