0

I'm trying to build an Asynchronous Chat Server and this is what I got so far:

Server

using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class StateObject { public Socket workSocket = null; public const int BufferSize = 1024; public byte[] buffer = new byte[BufferSize]; public StringBuilder sb = new StringBuilder(); } public class AsynchronousSocketListener { public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener() { } public static void StartListening() { byte[] bytes = new Byte[1024]; IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); try { listener.Bind(localEndPoint); listener.Listen(100); while (true) { allDone.Reset(); Console.WriteLine("Waiting for a connection..."); listener.BeginAccept(new AsyncCallback(AcceptCallback),listener); allDone.WaitOne(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } public static void AcceptCallback(IAsyncResult ar) { allDone.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); 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; StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -1) { Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",content.Length, content); Send(handler, content); } else { handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReadCallback), state); } } } private static void Send(Socket handler, String data) { byte[] byteData = Encoding.ASCII.GetBytes(data); handler.BeginSend(byteData, 0, byteData.Length, 0,new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { try { Socket handler = (Socket)ar.AsyncState; 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.Threading; using System.Text; 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; static String username = ""; static int a = 1; private static void StartClient() { try { Console.WriteLine("Username: "); username = Console.ReadLine(); while (a == 1) { IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint remoteEP = new IPEndPoint(ipAddress, port); Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); connectDone.WaitOne(); Console.WriteLine("Receiver: "); String receiver = Console.ReadLine(); Console.WriteLine("Message: "); String message = Console.ReadLine(); String Message = username + "[" + receiver + "[" + message + "<EOF>"; Send(client, Message); sendDone.WaitOne(); Receive(client); receiveDone.WaitOne(); Console.WriteLine("Response received : {0}", response); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void ConnectCallback(IAsyncResult ar) { try { Socket client = (Socket)ar.AsyncState; client.EndConnect(ar); 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); if (bytesRead > 0) { state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReceiveCallback), state); } else { if (state.sb.Length > 1) { response = state.sb.ToString(); } receiveDone.Set(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static void Send(Socket client, String data) { byte[] byteData = Encoding.ASCII.GetBytes(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); Console.WriteLine("Sent {0} bytes to server.", bytesSent); sendDone.Set(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { StartClient(); return 0; } } 

I'm able to send messages to the server and get back an answer, but the connection is cut every time and I have to reconnect it and like this I wouldn't be able to get messages after I send one. I'm looking for a way to connect my client to the server, send messages in both ways and stop the connection manualy. Furthermore I'm looking for a way to send messages from one client to another one and to send a message to all clients, who are connected to the server.

Another Question I have, how can I set up multiple ports and let the server listen to all ports? I wanted to open one port for the login and one port for the messages.

1
  • You close your socket in the SendCallback on the Server when you do handler.ShutDown(...); and handler.Close(); I think you need to leave the socket open until the connection is terminated by you. msdn.microsoft.com/en-us/library/wahsac9k(v=vs.110).aspx Commented Jul 4, 2017 at 13:53

2 Answers 2

1

I'm looking for a way to connect my client to the server, send messages in both ways and stop the connection manualy.

Closing the connection could be done by adding a disconnect call after the loop: client.Disconnect(false). After some exit condition you simply quit the loop.

It would be preferable to create the client in a using statement though, this way it will be disposed automatically.

Sign up to request clarification or add additional context in comments.

2 Comments

Could you give an example of the using statement?
0

but the connection is cut every time

because your explicitly close it in SendCallback

Socket handler = (Socket) ar.AsyncState; handler.Shutdown(SocketShutdown.Both); handler.Close(); 

You may call handler.BeginReceive instead

1 Comment

I don't get a response from the server if I call handler.BeginReceive instead.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.