Asynchronous Client Socket, receive buffer data ou

2019-08-03 09:02发布

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.

I was told in this post, that Data should never come out of order... Any ideas as to what I'm doing wrong to trigger this?

Here is a console output example of data that is in the correct order:

enter image description here Link to above picture

enter image description here Link to above picture

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);
            }
        });

    }

1条回答
beautiful°
2楼-- · 2019-08-03 09:44

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!

查看更多
登录 后发表回答