Julio Sanchez
Julio Sanchez

Reputation: 11

Ansychronous Socket Client ReceiveCallback not executing

Hi am am working on a C# Winforms Application using the sample code below:

https://msdn.microsoft.com/en-us/library/bbx2eya8(v=vs.110).aspx

It connects to the right IP address and port number but after sending a string command and waiting for a response the application gets stuck because the ReceiveCallback is not being executed therefore not setting the receiveDone ManualResetEvent. I am 100% sure im suppose to receive back a response but instead the application just gets stuck and does not execute the ReceiveCallback method. What could possibly be the reason why ReceiveCallback method is not being executed?

private static void Receive(Socket client)
    {
        try
        {
            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = client;

            // Begin receiving the data from the remote device.
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

 private static void ReceiveCallback(IAsyncResult ar)
    {
        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.
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                // Get the rest of the data.
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            else {
                // All the data has arrived; put it in response.
                if (state.sb.Length > 1)
                {
                    response = state.sb.ToString();
                }
                // Signal that all bytes have been received.
                receiveDone.Set();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

Context: The application is an interface for a DC electric Torque Tool controller. I connect to the controllers Ip address and port 4545 than i am able to send Open Protocol commands to change settings.

Upvotes: 1

Views: 1601

Answers (2)

Jiao
Jiao

Reputation: 31

Solution found at https://social.msdn.microsoft.com/Forums/vstudio/en-US/05dcda20-06f9-419b-bfc0-bcb8cfeb3693/socket-receivecallback-not-sending-notification-when-buffer-has-emptied?forum=csharpgeneral

Here is my fixing code. Check the "Add to fix" part please.

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.  
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
            }                                                       // Add to fix
                                                                    // Add to fix
            int bytesRemain = state.workSocket.Available;           // Add to fix
            if (bytesRemain>0)                                      // Add to fix
            {                                                       // Add to fix
                //  Get the rest of the data.  
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None,
                    new AsyncCallback(ReceiveCallback), state);
            }
            else
            {
                // All the data has arrived; put it in response.  

                if (state.sb.Length >= 1)                 //<-- Fixed from>1 to >=1
                    response = state.sb.ToString();
                else
                    response = ""; //OR null;

                // Signal that all bytes have been received.  
                receiveDone.Set();
            }
        }

Here is my analysis to why the orignal can't work:

  • I send a msg to the server like "*IDN?". The server replied a message of 34 letters like "Instrument ABC,xx,xx,xx". It has been read successfully by the ReceiveCallBack. so the bytesRead = 34.
  • But there is a check say if bytesRead >0, might be ,just might be there is still data there, so the ReceiveCallBack itself launched a new client.BeginReceive again.
  • But this time, there is no data from the server. so the client wait and wait and wait, the ReceiveCallBack never been called back again ...
  • So the else-branch of the ReceiveCallBack is never executed. Thus the 'response' variable never set and receiveDone never been Set either.

Upvotes: 3

Mark Davis
Mark Davis

Reputation: 36

I would add this as a comment, but I don't have the reputation.

  1. Where are you calling this from? You should have a loop which is calling Receive once you've connected to your socket. Could you show us the code where Receive is being called?

  2. What is the value of StateObject.BufferSize?

  3. Are any exceptions being thrown?

Upvotes: 0

Related Questions