So I have two things runner here. An iPad application talking to a python script running on a linux server. The python script is sending the iPad application data files of size ~1K bytes up to ~10K bytes. I'm having a very strange event that's occurring every once in a while (like maybe once every 100 or 200 tries).
I modeled my Asynchronous Client Socket from this example. In the ReceiveCallback function that I've posted below, I receive data into my buffer like this:
string stuffWeReceived = Encoding.ASCII.GetString(state.buffer,0,bytesRead);
But my problem is, sometimes I receive data out of order. And I stress the word sometimes. In my test, I had 5 iPads running my application side by side, and was sending all 5 ipads the same exact data. 99.9% of the time they receive the data correctly and in the right order, but 0.1% of the time ONE iPad will receive data out of order.
Here is a console output example of data that is in the correct order:
I know the python script on the server that is sending the data is sending data correctly because, as I mentioned above, in my test I have 5 iPads running the application and only 1 iPad will have this problem (this problem only happens a fraction of a percentage of the time...)
I am staring my Asynchronous Client Socket in a background thread as seen below:
AsyncClient_Thread = new Thread(() => AsyncClient.StartClient());
AsyncClient_Thread.IsBackground = true;
AsyncClient_Thread.Start();
public void StartClient()
{
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
string ipAddress = appDel.wallInteractionScreen.Host_WallServer;
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ipAddress), port);
// Create a TCP/IP socket.
ClientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
ClientSocket.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), ClientSocket);
connectDone.WaitOne();
Receive(ClientSocket);
receiveDone.WaitOne();
}
catch (Exception e) {
Console.WriteLine("Error in AsyncClient StartClient: ");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
// Console.WriteLine("Finished StartClient");
}
Here is my ReceiveCallback function
private static void ReceiveCallback( IAsyncResult ar )
{
AppDelegate appDel = (AppDelegate)UIApplication.SharedApplication.Delegate;
// I added this InvokeOnMainThread to see if it would solve the "data out of order problem", but it didn't
appDel.InvokeOnMainThread (delegate{
Console.WriteLine("ReceiveCallback IsMainThread = " + NSThread.IsMain);
try {
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
string stuffWeReceived = Encoding.ASCII.GetString(state.buffer,0,bytesRead);
string debugString = "~~ReceiveCallback~~ len = " + stuffWeReceived.Length + " bytesRead = " + bytesRead + ": " + stuffWeReceived;
if ( appDel.diagnosticsScreen.DebugAsyncReceiveBuffer_Switch.On )
{
appDel.diagnosticsScreen.AppendToDebugLog(debugString);
}
Console.WriteLine(debugString);
// Send this data to be received
appDel.wallInteractionScreen.ChitterChatter.ReceiveSomeData(stuffWeReceived);
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
} else {
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e) {
Console.WriteLine("Error in AsyncClient ReceiveCallback: ");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
});
}
This ended up being a Threading/Locking problem in my code on the C# side. I rewrote my locking mechanisms from scratch and now have things working 100% of the time. Thanks to everyone who helped me see this one through!