Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a simple asynchronous socket server written in C# (pretty much Microsoft's example ), however the issue with this example is that it accepts only one message from a client and then shuts down. I want this server to stay alive after receiving any message.

This question has been asked before here , and the answer & comments explain that the resolution to this is simply to call handler.beginReceive within the SendCallback function, however to do this requires passing in a state variable. This is something I am unsure of doing with Async programming as I'm pretty new to it.

With the example below, how can I carry my state object from the Send function to the SendCallback function?

Server code:

// Asynchronous Server Socket Example
// http://msdn.microsoft.com/en-us/library/fx6588te.aspx
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
public class StateObject
    // Client  socket.
    public Socket workSocket = null;
    // Size of receive buffer.
    public const int BufferSize = 1024;
    // Receive buffer.
    public byte[] buffer = new byte[BufferSize];
    // Received data string.
    public StringBuilder sb = new StringBuilder();
public class GetState
public class AsynchronousSocketListener
    // Thread signal.
    public static ManualResetEvent allDone = new ManualResetEvent(false);
    public AsynchronousSocketListener()
    public static void StartListening()
        // Data buffer for incoming data.
        byte[] bytes = new Byte[1024];
        // Establish the local endpoint for the socket.
        // The DNS name of the computer
        // running the listener is "host.contoso.com".
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
        // Create a TCP/IP socket.
        Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        // Bind the socket to the local endpoint and listen for incoming connections.
            listener.Bind(localEndPoint);
            listener.Listen(100);
            while (true)
                // Set the event to nonsignaled state.
                allDone.Reset();
                // Start an asynchronous socket to listen for connections.
                Console.WriteLine("Waiting for a connection...");
                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                // Wait until a connection is made before continuing.
                allDone.WaitOne();
        catch (Exception e)
            Console.WriteLine(e.ToString());
        Console.WriteLine("\nPress ENTER to continue...");
        Console.Read();
    public static void AcceptCallback(IAsyncResult ar)
        // Signal the main thread to continue.
        allDone.Set();
        // Get the socket that handles the client request.
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);
        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = handler;
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
    public static void ReadCallback(IAsyncResult ar)
        String content = String.Empty;
        // Retrieve the state object and the handler socket
        // from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;
        // Read data from the client socket. 
        int bytesRead = handler.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));
            // Check for end-of-file tag. If it is not there, read 
            // more data.
            content = state.sb.ToString();
            if (content != null)
                // All the data has been read from the 
                // client. Display it on the console.
                Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
                    content.Length, content);
                // Echo the data back to the client.
                Send(handler, content, state);
                // Not all data received. Get more.
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
    private static void Send(Socket handler, String data, StateObject state)
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.ASCII.GetBytes(data);
        // Begin sending the data to the remote device.
        handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
    private static void SendCallback(IAsyncResult ar)
            // Retrieve the socket from the state object.
            Socket handler = (Socket)ar.AsyncState;
            // Complete sending the data to the remote device.
            int bytesSent = handler.EndSend(ar);
            Console.WriteLine("Sent {0} bytes to client.", bytesSent);
            /// ******* WIP ******** //
            //handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
            //handler.Shutdown(SocketShutdown.Both);
            //handler.Close();
        catch (Exception e)
            Console.WriteLine(e.ToString());
    public static int Main(String[] args)
        StartListening();
        return 0;
    private Socket listener;
    private byte[] buffer = new byte[8192]; // Buffer to store data from clients.
    public void StartListening()
        listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        listener.Bind(new IPEndPoint(localIPAddress, listeningPort));
        listener.Listen(20);
        listener.BeginAccept(OnSocketAccepted, null);
    private void OnSocketAccepted(IAsyncResult result)
        // This is the client socket, where you send/receive data from after accepting. Keep it in a List<Socket> collection if you need to.
        Socket client = listener.EndAccept(result);
        // Pass in the client socket as the state object, so you can access it in the callback.
        client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, OnDataReceived, client); // Start receiving data from this client.
        listener.BeginAccept(OnSocketAccepted, null); // Start a new async accept operation to accept incoming connections from other clients.
    private void OnDataReceived(IAsyncResult result)
        // This is the client that sent you data. AsyncState is exactly what you passed into the state parameter in BeginReceive
        Socket client = result.AsyncState as Socket;
        int received = client.EndReceive(result);
        // Handle received data in buffer, send reply to client etc...
        // Start a new async receive on the client to receive more data.
        client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, OnDataReceived, client);

As you can see it's pretty much a lot of recursive callbacks. The basic idea is that you call BeginAccept to start accepting the first connection, then once your callback fires you accept the connection with EndAccept and start a new BeginAccept to start accepting more connections. This same logic applies to BeginReceive and EndReceive when you start communicating with the clients. With this logic the server will continuously accept incoming connections and clients will also be able to continously send data to server.

In your example you get your listener from the AsyncState but you didn't call BeginAccept again to accept more incoming connections, which probably explains why your server only accepts 1 connection and shuts down.

For the state parameter in BeginSend, you can actually just put your BeginReceive right after your Send() method to save yourself the hassle:

Send(handler, content, state);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);

It's much better to just fire up a background thread and use blocking calls.

Here's a TcpServer using the TcpListener and NetworkStream

public class TcpServer
    public void Run(string address, int port)
        var listener = new TcpListener(IPAddress.Parse(address), port);
        listener.Start();
        while (true)
            TcpClient tcpclient = null;
            NetworkStream netstream = null;
                tcpclient = listener.AcceptTcpClient();
                Console.WriteLine("Client connected from " + tcpclient.Client.LocalEndPoint.ToString());
                netstream = tcpclient.GetStream();
                var responsewriter = new StreamWriter(netstream) { AutoFlush = true };
                while (true)
                    if (IsDisconnected(tcpclient))
                        throw new Exception("Client disconnected gracefully");
                    if (netstream.DataAvailable)             // handle scenario where client is not done yet, and DataAvailable is false. This is not part of the tcp protocol.
                        string request = Read(netstream);
                        Console.WriteLine("Client sent: " + request);
                        responsewriter.Write("You sent: " + request);
            catch (Exception ex)
                netstream.Close();
                tcpclient.Close();
                Console.WriteLine(ex.Message);
    private bool IsDisconnected(TcpClient tcp)
        if (tcp.Client.Poll(0, SelectMode.SelectRead))
            byte[] buff = new byte[1];
            if (tcp.Client.Receive(buff, SocketFlags.Peek) == 0)
                return true;
        return false;
    private string Read(NetworkStream netstream)
        byte[] buffer = new byte[1024];
        int dataread = netstream.Read(buffer, 0, buffer.Length);
        string stringread = Encoding.UTF8.GetString(buffer, 0, dataread);
        return stringread;

To run it

static void Main()
    ThreadPool.QueueUserWorkItem(w => {
        var asyncserver = new TcpServer();
        asyncserver.Run("192.168.0.7", 5055); // or whatever your local IP Address is
    Console.WriteLine("Press [Enter] to quit");
    Console.ReadLine();
                Thanks for your input. Can you please elaborate on why your suggested approach is better?
– devklick
                Jun 10, 2018 at 15:48
                It's a matter of preference, but I think the Begin.. methods and the code you have to write with the state parameter and ManualResetEvent is somewhat ugly, and not something I would want to maintain
– rayh
                Jun 10, 2018 at 17:08
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.