2

I've searched for the better part of the day trying to figure this out, and I'm certain I'm missing a simple solution somewhere.

I'm using an asynchronous socket client connection to monitor incoming data from a TCP connection. I've implemented a ManualResetEvent and Callback method as recommended by the msdn sample, but the Callback method is not able to invoke the methods used to output the received data to my Windows form. How do I take the data received from the socket, and send it to the text box in my form?

I'm certain there's a simple trick that I'm missing somewhere. The sample code is written for a console application. How do I have the form react to incoming data from the Socket?

Update:

I think you've got me on the right track. I tried putting in code to use delegates, but I clearly don't quite understand how delegates work, as it keeps throwing the following errors:

An object reference is required for the non-static field, method, or property 'APRS_SMS_Gateway.MainForm.SockOutputDelegate'

Can you get me a little closer? It's the ConnectCallBack Handler that I'm trying to work on right now, but I want to use the same method (SockOutput) from all the CallBacks.

public partial class MainForm : Form
{
    private AutoResetEvent receiveNow;

    public delegate void SockOutputDelegatetype(string text); // Define delegate type
    public SockOutputDelegatetype SockOutputDelegate;

    // The port number for the remote device.
    private const int port = 14580;

    // ManualResetEvent instances signal completion.
    private static ManualResetEvent connectDone =
        new ManualResetEvent(false);
    private static ManualResetEvent sendDone =
        new ManualResetEvent(false);
    private static ManualResetEvent receiveDone =
        new ManualResetEvent(false);

    // The response from the remote device.
    private static String response = String.Empty;

    public MainForm()
    {

        InitializeComponent();

        SockOutputDelegate = new SockOutputDelegatetype(SockOutput);

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        CommSetting.APRSServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //StartClient();

    }

    private void StartClient()
    {
        try
        {
            IPHostEntry ipHostInfo = Dns.GetHostEntry("rotate.aprs.net");
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket.
            //Socket APRSServer = new Socket(AddressFamily.InterNetwork,
            //    SocketType.Stream, ProtocolType.Tcp);

            // Connect to the remote endpoint.
            CommSetting.APRSServer.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), CommSetting.APRSServer);
            connectDone.WaitOne();

            //Show the connect string from the host
            Receive(CommSetting.APRSServer);
            //receiveDone.WaitOne();

            //Show the connection response
            //SockOutput(response);
        }
        catch (Exception e)
        {
            SockOutput(e.ToString());
        }
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket APRSServer = (Socket)ar.AsyncState;

            // Complete the connection.
            APRSServer.EndConnect(ar);

            // Signal that the connection has been made.
            connectDone.Set();
        }
        catch (Exception e)
        {
            MainForm.Invoke(MainForm.SockOutputDelegate, e.ToString());
        }
    }

    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)
        {
            //throw new ApplicationException(e.ToString());
            response = 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)
        {
            response = e.ToString();
        }
    }


    void SockOutput(string text)
    {
            txtSockLog.AppendText(text);
            txtSockLog.AppendText("\r\n");
    }



}

}

Prdufresne
  • 296
  • 2
  • 15

1 Answers1

2

It sounds like your socket side is working OK, its just updating the winform that's causing problems. You may find your answer here Update WinForm Controls from another thread _and_ class.

Community
  • 1
  • 1
MarcF
  • 3,169
  • 2
  • 30
  • 57