Async Sample Client Socket receive in a loop - c#

I want to receive new messages from server in a loop. But when I use the code below, it stops on receiveDone in while loop. And it doesn't receive any message from server. How to change the below code or write a new one, which receives messages and popup them on screen.
// State object for receiving data from remote device.
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient {
// The port number for the remote device.
private const int port = 1200;
// 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;
private static void StartClient() {
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send data to the remote device.
Send(client,"HELLO");
sendDone.WaitOne();
while(true)
{
Receive(client);
receiveDone.WaitOne();
if(!string.IsNullOrWhiteSpace(response))
Console.WriteLine(response);
}
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar) {
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
private static void Receive(Socket client) {
// 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);
}
private static void ReceiveCallback(IAsyncResult ar) {
// 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();
}
}
private static void Send(Socket client, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar) {
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
public static int Main(String[] args) {
StartClient();
return 0;
}
}
The above code comes from msdn. I read carefully everything on the site, but there is no answer.

You are getting an exception and exiting the program. Try following fix :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ConsoleApplication48
{
class Program
{
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int port = 1200;
// 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;
private static void StartClient()
{
// Connect to a remote device.
try
{
string LocalHostName = Dns.GetHostName();
IPHostEntry LocalHostIPEntry = Dns.GetHostEntry(LocalHostName); ;
IPAddress ipAddress = LocalHostIPEntry.AddressList.Where(x => !x.IsIPv6LinkLocal).FirstOrDefault();
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send data to the remote device.
Send(client, "HELLO");
sendDone.WaitOne();
while (true)
{
Receive(client);
receiveDone.WaitOne();
if (!string.IsNullOrWhiteSpace(response))
Console.WriteLine(response);
}
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
private static void Receive(Socket client)
{
// 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);
}
private static void ReceiveCallback(IAsyncResult ar)
{
// 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));
Send(client, "HELLO");
// 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();
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
// Get the socket that handles the client request.
TcpListener listener = (TcpListener) ar.AsyncState;
Socket handler = listener.Server.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ListenerReadCallback), state);
}
public static void ListenerReadCallback(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) {
handler.BeginSend(state.buffer, 0, bytesRead, 0,
new AsyncCallback(ListenerSendCallback), handler);
}
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ListenerReadCallback), state);
}
private static void ListenerSendCallback(IAsyncResult ar) {
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
}
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 1200);
listener.Start();
listener.Server.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );
StartClient();
}
}
}
}

Related

How does one identify and differentiate clients connected in a client-server socket application?

In the scenario where there is a SINGLE asynchronous socket server, and n-number of clients connected, on the server side how can I differentiate the clients? I need to know which client the data is coming from. Note - It may not be possible to append an identifier to requests.
Clients are created at runtime:
public void CreateSockets()
{
Parallel.For(1, Convert.ToInt32(numericUpDown1.Value) + 1, i =>
{
new Thread(() => Connect(i)).Start();
});
}
Abbreviated client creation loop:
public void Connect(int i)
{
ClientSocket[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
ClientSocket[i].Connect(ip, port);
}
catch (SocketException sex)
{
Console.WriteLine(sex);
}
RequestLoop();
}
The sockets are being created, connect, and are sending data to the server. The server is directly from the MS site examples of Asynchronous Socket Server.
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
{
// 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();
// Client socket.
public Socket workSocket = null;
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener()
{
}
public static void StartListening()
{
// 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.
try {
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.IndexOf("<EOF>") > -1) {
// 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);
} else {
// 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)
{
// 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)
{
try
{
// 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);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
The combination of srcip:srcport:dstip:dstport is a unique value.
Use that Value to identify your client. When a client connects, have the client send an identifier. Maintain state in your server mapping that combination to your client.
You will never have two identical values of this on any socket on your network. (Except in the case of private networks with identical ip addresses).

C# Async Socket Server - BeginReceive in Callback

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.
try
{
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);
}
else
{
// 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)
{
try
{
// 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;
}
}
This is how I would do it:
public class AsynchronousSocketServer
{
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;
try
{
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();
}

TCP Server with bi-directional communication

I have attempted to create a TCP service that is able to achieve what I wish but sadly I am getting stuck at the last hurdle.
The Scenario:
A single server instance is running with 10 clients all connected, a client will send a command, and receive the response. This is all working fine. However the last scenario isn't working
When a client issues an "UPDATE" command, the server should then send a message back to all connected clients that they need to do something.
Example Comms:
1
Client A GetTime -----> Server
Client A <----- Time is... Server
2
Client A UPDATE ------> Server
Client A <------- Ack Server
Client A <------- DoUpdate Server
Client B <------- DoUpdate Server
Client C <------- DoUpdate Server
Comms 1 abover works, mainly because of the call to send and call to reeive, but for comms 2 I cannot workout how I can achieve this, at least not without opening a second port for the communication which isn't ideal.
Current attempt based on Microsoft Article
Server
class Program
{
public static int Main(String[] args)
{
AsynchronousSocketListener.StartListening();
return 0;
}
}
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 AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent AllDone = new ManualResetEvent(false);
public static void StartListening()
{
// Data buffer for incoming data.
//var 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.Resolve(Dns.GetHostName());
//??IPAddress ipAddress = ipHostInfo.AddressList[0];
//??IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3030);
// Create a TCP/IP socket.
var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(new IPEndPoint(IPAddress.Any, 3030));
//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((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.
var listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
var state = new StateObject {WorkSocket = handler};
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
public static void ReadCallback(IAsyncResult ar)
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
var 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.
var content = state.Sb.ToString();
if (content.IndexOf("<EOF>", StringComparison.Ordinal) > -1)
{
// 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);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
var byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var 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);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/*
public static int Main(String[] args)
{
StartListening();
return 0;
}
* */
}
Client Code
class Program
{
public static int Main(String[] args)
//static void Main(string[] args)
{
Console.Title = "Client ";
AsynchronousClient.StartClient();
Console.ReadLine();
return 0;
}
}
public class StateObject
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder Sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int Port = 3030;
// ManualResetEvent instances signal completion.
private static readonly ManualResetEvent ConnectDone =
new ManualResetEvent(false);
private static readonly ManualResetEvent SendDone =
new ManualResetEvent(false);
private static readonly ManualResetEvent ReceiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String _response = String.Empty;
public static void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
//??IPHostEntry ipHostInfo = Dns.Resolve("localhost");
//??IPAddress ipAddress = ipHostInfo.AddressList[0];
//??IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
//client.BeginConnect(remoteEP,
//new AsyncCallback(ConnectCallback), client);
var remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), Port);
client.BeginConnect(remoteEP, ConnectCallback, client);
ConnectDone.WaitOne();
// set receive to another thread so we can constantly receive, doesn't work as intended
//var thread = new Thread(() => ReadThread(client));
//thread.Start();
// Send test data to the remote device.
Send(client, "This is a test<EOF>");
SendDone.WaitOne();
//test remove
// Receive the response from the remote device.
Receive(client);
ReceiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", _response);
// Release the socket.
//client.Shutdown(SocketShutdown.Both);
//client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
// doesn't work as expected
private static void ReadThread(object ar)
{
var client = (Socket)ar;
while (true)
{
Receive(client);
ReceiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", _response);
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint);
// Signal that the connection has been made.
ConnectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
var state = new StateObject {WorkSocket = client};
// Begin receiving the data from the remote device.
client.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, 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.
var 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, 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());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
var byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
SendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/*
public static int Main(String[] args)
{
StartClient();
return 0;
}
*/
}
Previous system that worked
Server:
class Program
{
private static byte[] buffer = new byte[1024];
public static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public static List<Socket> clientSockets = new List<Socket>();
static void Main(string[] args)
{
Console.Title = "Server, " + clientSockets.Count + " clients are connected";
SetupServer();
Console.ReadLine();
}
public static void SetupServer()
{
Console.WriteLine("Setting up server...");
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 3030));
_serverSocket.Listen(10);
_serverSocket.BeginAccept(AcceptCallback, null);
Console.ReadLine();// stops cmd from closing
}
public static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _serverSocket.EndAccept(AR);
if (!clientSockets.Contains(socket))
clientSockets.Add(socket);
IPEndPoint remoteIPEndPoint = socket.RemoteEndPoint as IPEndPoint;
Console.WriteLine(remoteIPEndPoint.Address);
Console.WriteLine("Client Connected");
Console.Title = "Server, " + clientSockets.Count + " clients are connected";
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
_serverSocket.BeginAccept(AcceptCallback, null);
}
private static void RecieveCallBack(IAsyncResult AR)
{
var socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
var databuff = new byte[received];
Array.Copy(buffer, databuff, received);
string s = Encoding.ASCII.GetString(databuff);
Console.WriteLine("Text Received: " + s);
string response = string.Empty;
switch (s.ToLower())
{
case "get time":
response = DateTime.Now.ToLongTimeString();
break;
case "hello":
response = "olleh";
break;
case "update clients":
response = "";
SendData("Ack", socket);
doUpdateClients();
break;
default:
response = "Invavlid Request";
break;
}
SendData(response, socket);
}
private static void SendData(string Data, Socket socket)
{
byte[] data = Encoding.ASCII.GetBytes(Data);
socket.BeginSend(data, 0, data.Length, SocketFlags.None, sendCallback, socket);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
}
private static void doUpdateClients()
{
// need to send an update message to all the clients
var upd = new Thread((UpdateClients));
upd.Start();
}
private static void UpdateClients()
{
Thread.Sleep(5000);
foreach (var sock in clientSockets)
{
SendData("UpdateClients", sock);
}
}
private static void sendCallback(IAsyncResult AR)
{
var socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
//
}
}
Client:
class Program
{
private static byte[] buffer = new byte[1024];
public static Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
Console.Title = "Client ";
LoopConnect();
//ReceiveLoopStart();
//_clientSocket.Listen(10);
SendLoop();
Console.ReadLine();
}
private static void LoopConnect()
{
while (!_clientSocket.Connected)
{
try
{
_clientSocket.Connect(IPAddress.Parse("127.0.0.1"), 3030);
}
catch (SocketException se)
{
}
}
Console.WriteLine("Connected");
}
private static void ReceiveLoopStart()
{
//_clientSocket.Bind(new IPEndPoint(IPAddress.Any, 3030));
//_clientSocket.Listen(10);
_clientSocket.BeginAccept(AcceptCallback, null);
Thread receiveThread = new Thread(ReceiveLoop);
receiveThread.Start();
}
private static void ReceiveLoop()
{
_clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, _clientSocket);
_clientSocket.BeginAccept(AcceptCallback, null);
}
private static void RecieveCallBack(IAsyncResult AR)
{
int received = _clientSocket.EndReceive(AR);
var databuff = new byte[received];
Array.Copy(buffer, databuff, received);
string s = Encoding.ASCII.GetString(databuff);
Console.WriteLine("Text Received: " + s);
string response = string.Empty;
switch (s.ToLower())
{
case "get time":
response = DateTime.Now.ToLongTimeString();
break;
case "hello":
response = "olleh";
break;
default:
response = "Invavlid Request";
break;
}
}
public static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _clientSocket.EndAccept(AR);
Console.WriteLine("Client Connected");
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
_clientSocket.BeginAccept(AcceptCallback, null);
}
private static void SendLoop()
{
while (true)
{
Console.Write("Enter Request: ");
string req = Console.ReadLine();
var buffer = Encoding.ASCII.GetBytes(req);
_clientSocket.Send(buffer);
var tempBuff = new byte[1024];
int rec = _clientSocket.Receive(tempBuff);
var data = new byte[rec];
Array.Copy(tempBuff, data, rec);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
}
}
}
}
I don't have an example up my sleeve here in C# but what you need to learn is to use the select api.
You only need a single thread to do this. You use the same thread to process all sockets that are in use at any point in time.
If nobody is connected you only have the listening socket. And you then only use the select api to watch what happens on that socket. Select is a blocking call when no timeout is specified. If data is available, then that means that you can call accept. The result of accept is as you know another socket. You now use 2 sockets in select. Again select will block until one of those sockets has data. Perhaps the listening socket again, so you get another socket after calling accept. You now use 3 sockets in select. Suppose now one of the accept sockets have data available you will see that by the using the select api properly. And you can then use any of those sockets to send something over it, except of course the listening socket that is not intended for sending.
More info can be found here :
http://www.codeproject.com/Articles/20066/A-scalable-client-server-using-select-socket-funct
It uses what I explained and gives more elaborate explanations too.
I'm not getting in to your design , but it seems like you can't even reference the other clients.
why don't you save a collection of sockets like so :
private List<Socket> _handlers = new List<Socket>();
public static void AcceptCallback(IAsyncResult ar)
{
Socket handler = listener.EndAccept(ar);
var state = new StateObject {WorkSocket = handler};
handlers.Add(handler);
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
And then on receive according to the message type or whatever you should notify these clients.( all of them not just the one currently passed to the ReciveCallback.
public static void ReadCallback(IAsyncResult ar)
{
if("<EOF>")
{
foreach(var h in _handlers)
{
Send(h,data);
}
}
}

Close Client after the server respond

The only thing i want to change is to close the client connection after the client send message to the server and received respond from the server.
what i need to change in the client code ?
Server
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 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.Resolve(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = System.Net.IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
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.IndexOf("<EOF>") > -1)
{
// 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);
}
else
{
// 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)
{
// 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)
{
try
{
// 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);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
Client:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class Program
{
public static ManualResetEvent connectDone = new ManualResetEvent(false);
public static ManualResetEvent sendDone = new ManualResetEvent(false);
public static ManualResetEvent receiveDone = new ManualResetEvent(false);
public static void Connect(EndPoint remoteEP, Socket client)
{
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(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)
{
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)
{
string response = state.sb.ToString();
Console.WriteLine(response);
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static void Main(string[] args)
{
IPAddress ipAddress = System.Net.IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
Socket sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
Connect(localEndPoint, sock);
string packet;
while (true)
{
packet = Console.ReadLine();
packet += "<EOF>";
Send(sock, packet);
Receive(sock);
connectDone.WaitOne();
}
}
}
The while loop in Main will run indefinitely.
while (true)
{
packet = Console.ReadLine();
packet += "<EOF>";
Send(sock, packet);
Receive(sock);
connectDone.WaitOne();
}
either remove it entirely (so that it runs only once) or add in a condition to exit the while loop.
as Diego pointed out the in the comments, you should close the socket after you are done, by
sock.Close();

Asynchronous States Acting Odd

I'm attempting to create an asynchronous server/client chat program. While I've got a lot of it down I'm hitting a roadblock. When a client sends a packet to the server it is read just fine and further is echoed back to that client with no issues. If another client is connected, it will EVENTUALLY receive the packet...but it may take several send calls. Another issue is the StateObject buffer (at least thats what I think it is) isn't being cleared despite my best efforts. So the resulted output is very erratic and odd. Any direction would be very helpful!
Server.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections.Generic;
namespace Async_Server
{
// 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 StatesHandler
{
public List<StateObject> States = new List<StateObject>();
public int Counter = 0;
}
public class AsynchronousSocketListener
{
public static Async_Server.StatesHandler stateshandler = new StatesHandler();
// 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.Resolve(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
//IPHostEntry ipHostInfo = Dns.GetHostByName(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
//IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
IPAddress ipAddress = IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
Console.WriteLine("Waiting for a connection # " + ipAddress.ToString());
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
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();
}
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();
//Store state instance in stateshandler
stateshandler.States.Add(state);
stateshandler.Counter++;
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
Console.WriteLine("Connection accepted from: " + handler.RemoteEndPoint.ToString());
}
public static void ReadCallback(IAsyncResult ar)
{
try
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
if ((StateObject)ar.AsyncState != null)
{
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.IndexOf("<EOF>") > -1)
{
// 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(ar, content);
content = null;
}
else
{
// Not all data received. Get more.
try
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e);
Console.Read();
}
}
}
else
{
Console.WriteLine("RAWR");
Console.Read();
}
}
}
catch (Exception e)
{
Console.WriteLine("Connection terminated from: ", e);
}
}
private static void Send(IAsyncResult ar, String data)
{
/*
for (int i = 0; i < stateshandler.Counter; i++)
{
StateObject state = stateshandler.States[i];
Socket handler = state.workSocket;
// 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), state);
}
*/
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// 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), state);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
}
public static int Main(String[] args)
{
try
{
StartListening();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
Console.Read();
return 0;
}
}
}
Client.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class Program
{
public static ManualResetEvent connectDone = new ManualResetEvent(false);
public static ManualResetEvent sendDone = new ManualResetEvent(false);
public static ManualResetEvent receiveDone = new ManualResetEvent(false);
public static void Connect(EndPoint remoteEP, Socket client)
{
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(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)
{
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));
Console.WriteLine(state.sb.ToString());
// 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)
{
string response = state.sb.ToString();
Console.WriteLine(response);
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static void Main(string[] args)
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Connect(localEndPoint, sock);
string packet;
while (true)
{
packet = Console.ReadLine();
packet += "<EOF>";
Send(sock, packet);
Receive(sock);
connectDone.WaitOne();
packet = null;
}
}
}

Categories