1
\$\begingroup\$

I've made some modifications to the async client example found on MSDN for the purpose of testing a server application.

It works entirely as I expect and/or want, even running multiple clients, but as I intend to use this as the foundation of the actual client and not just for testing I figured I'd see if I'm doing anything wrong or if anything could be optimized.

My main point of concern here being the usage of Task.Run to initialize the send and receive functions for the client. I've seen instances that suggest using the Task.Factory is something I want to avoid unless needed and I've seen instances that suggest Task.Factory.FromAsync is what I want to use. Even then, I've only seen FromAsync being proposed with BeginSend, so I'm also not sure if this applies to BeginRecieve as well.

While most of it is from msdn, I've had past issues with examples. Having said that, if you see anything else that stands out to you, please feel free to point that out to me as well.

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Threading.Tasks;

public class StateObject
{  
    public Socket workSocket = null; 
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];  
    public StringBuilder sb = new StringBuilder();
}

public class AsynchronousClient
{ 
    private const int port = 11000;

    private static ManualResetEvent connectDone =
        new ManualResetEvent(false);
    private static ManualResetEvent sendDone =
        new ManualResetEvent(false);
    private static ManualResetEvent receiveDone =
        new ManualResetEvent(false);

    private static String response = String.Empty;

    public static void Main(String[] args)
    {
        StartClient();
    }

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

            Socket client = new Socket(ipAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();

            Task.Run(() => Receive(client));

            Task.Run(() => StartTest(client));

            Console.Read();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void StartTest(Socket client)
    {
        for (int i = 0; i <= 3000; i++)
        {
            Send(client, string.Format
                ("This Is A Test Message ({0})<|>", i));
            sendDone.WaitOne();
        }
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        { 
            Socket client = (Socket)ar.AsyncState;
            client.EndConnect(ar);

            Console.WriteLine("Socket connected to {0}",
                client.RemoteEndPoint.ToString());

            connectDone.Set();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void Receive(Socket client)
    {
        try
        { 
            StateObject state = new StateObject();
            state.workSocket = client;
            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
        {  
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            int bytesRead = client.EndReceive(ar);
            state.sb.Append
                (Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

            Console.WriteLine(state.sb.ToString()); state.sb.Clear();

            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void Send(Socket client, String data)
    {  
        byte[] byteData = Encoding.ASCII.GetBytes(data);

        Console.WriteLine("Sending: " + data);

        client.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), client);
    }

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;

            int bytesSent = client.EndSend(ar);

            sendDone.Set();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ A bit of a shot in the dark, but I'm going to shamelessly link to an older answer of mine about sending discrete messages over TCP which discusses some of the fun that can be had with that, because I think the rest of the web (looking at you, MSDN) does a poor job of presenting this. Presently your code appears to just send a stream of ASCII from server to client, but rarely is this the final objective. Sorry if I'm jumping to conclusions about your intentions. \$\endgroup\$ – VisualMelon Jan 22 '18 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.