异步客户端套接字,无序接收缓冲区数据 [英] Asynchronous Client Socket, receive buffer data out of order

查看:41
本文介绍了异步客户端套接字,无序接收缓冲区数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我在这里有两件事.一个与在Linux服务器上运行的python脚本对话的iPad应用程序.python脚本正在发送大小为〜1K字节至最大〜10K字节的iPad应用程序数据文件.我遇到了一个非常奇怪的事件,它每隔一段时间就会发生一次(例如,每100或200次尝试一次).

链接到上述图片

我知道正在发送数据的服务器上的python脚本正在正确发送数据,因为如上所述,在我的测试中,我有5台iPad运行该应用程序,只有1台iPad会出现此问题(只会发生此问题一小部分的时间...)

我在后台线程中盯着异步客户端套接字,如下所示:

  AsyncClient_Thread = new Thread(()=> AsyncClient.StartClient());AsyncClient_Thread.IsBackground = true;AsyncClient_Thread.Start();公共无效StartClient(){//连接到远程设备.尝试 {//为套接字建立远程端点.字符串ipAddress = appDel.wallInteractionScreen.Host_WallServer;IPEndPoint remoteEP =新的IPEndPoint(IPAddress.Parse(ipAddress),端口);//创建一个TCP/IP套接字.ClientSocket =新的Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//连接到远程端点.ClientSocket.BeginConnect(remoteEP,新的AsyncCallback(ConnectCallback),ClientSocket);connectDone.WaitOne();接收(ClientSocket);receiveDone.WaitOne();}捕获(异常e){Console.WriteLine("AsyncClient StartClient中的错误:");Console.WriteLine(e.Message);Console.WriteLine(e.StackTrace);}//Console.WriteLine("Finished StartClient");} 

这是我的ReceiveCallback函数

 私有静态无效ReceiveCallback(IAsyncResult ar){AppDelegate appDel =(AppDelegate)UIApplication.SharedApplication.Delegate;//我添加了此InvokeOnMainThread来查看它是否可以解决数据乱序问题",但是并没有解决appDel.InvokeOnMainThread(委托{Console.WriteLine("ReceiveCallback IsMainThread =" + NSThread.IsMain);尝试 {//检索状态对象和客户端套接字//从异步状态对象开始.StateObject状态=(StateObject)ar.AsyncState;套接字客户端= state.workSocket;//从远程设备读取数据.int bytesRead = client.EndReceive(ar);如果(bytesRead> 0){//可能会有更多数据,因此请存储到目前为止接收到的数据.字符串stuffWeReceived = Encoding.ASCII.GetString(state.buffer,0,bytesRead);字符串debugString ="~~ ReceiveCallback ~~ len =" + stuffWeReceived.Length +"bytesRead =" + bytesRead +:" + stuffWeReceived;如果(appDel.diagnosticsScreen.DebugAsyncReceiveBuffer_Switch.On){appDel.diagnosticsScreen.AppendToDebugLog(debugString);}Console.WriteLine(debugString);//发送要接收的数据appDel.wallInteractionScreen.ChitterChatter.ReceiveSomeData(stuffWeReceived);//获取其余数据.client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,新的AsyncCallback(ReceiveCallback),状态);} 别的 {//表示已收到所有字节.receiveDone.Set();}}捕获(异常e){Console.WriteLine("AsyncClient ReceiveCallback中的错误:");Console.WriteLine(e.Message);Console.WriteLine(e.StackTrace);}});} 

解决方案

这最终是我在C#端代码中的线程/锁定问题.我从头开始重写了锁定机制,现在有100%的时间可以正常工作.感谢所有帮助我了解这一点的人!

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:

Link to above picture

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

    }

解决方案

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!

这篇关于异步客户端套接字,无序接收缓冲区数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆