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 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.