0

I've been coding a chat program that is made of two parts: server and client. The server uses TcpListener to listen for incoming requests to join the server, and the client uses TcpClient that it uses to connect to the server, and send messages. So far I have the handshake that is the first message sent when the client connects - it contains the client's IP address and the nickname set. I don't know how to make the server to listen asynchronously, because if it's not async, then the chat will be client -> server -> client -> server whereas it needs to be connected to multiple clients at once, and receive multiple messages at once. My code so far is written synchronously:
Client:

public void StartClient(string serverIP) { ReadWrite rw = new ReadWrite(); string nick = rw.GetNick(); string handshakeContents = "HANDSHAKE:" + nick + ":" + GetIP(); Int32 serverPort = 1336; // yay TcpClient client = new TcpClient(serverIP, serverPort); Console.WriteLine("Sending initial handshake: {0}", handshakeContents); Byte[] data = System.Text.Encoding.ASCII.GetBytes(handshakeContents); // Convert handshakeContents to Byte[] NetworkStream stream = client.GetStream(); // Instantiate object "stream" for use in read/write stream.Write(data, 0, data.Length); // Send handshakeContents in Byte[] to server Console.WriteLine(" - Connecting to IlanChat Server on ip {0}", serverIP); Thread.Sleep(1000); // sleep 1s data = new Byte[256]; string responseHandshake = String.Empty; // response handshake from server Int32 bytes = stream.Read(data, 0, data.Length); // Read handshake. responseHandshake = System.Text.Encoding.ASCII.GetString(data, 0, bytes); // Decode from Byte[] to ASCII string Console.WriteLine(" - Received response handshake: {0}", responseHandshake); Console.WriteLine(" - Successfully connected to IlanChat server on IP {0}", serverIP); // display message Thread.Sleep(2000); Console.Clear(); List<string> messagesRecieved = new List<string>(); while(true) { Console.Clear(); foreach (string msg in messagesRecieved) { Console.WriteLine(msg); } Console.WriteLine(); Console.Write("Enter message: "); string msgRaw = Console.ReadLine(); string sendMsg = nick + ": " + msgRaw; data = new Byte[256]; data = System.Text.Encoding.ASCII.GetBytes(sendMsg); stream.Write(data, 0, data.Length); // finish this async shit } } 

Server:

 List<string> clientIP = new List<string>(); List<string> clientNicks = new List<string>(); string responseHandshake = "hello"; Int32 serverPort = 1336; IPAddress machineIP = IPAddress.Parse(GetIP()); Console.Clear(); Console.WriteLine(" - Starting IlanChat server on IP {0}", machineIP); TcpListener server = null; server = new TcpListener(machineIP, serverPort); server.Start(); Byte[] buffer = new Byte[256]; String data = null; Console.WriteLine("Successfully started IlanChat server!"); while (true) // first alpha - only one user at a time { Console.WriteLine(); Console.WriteLine("Waiting for connections.."); TcpClient client = server.AcceptTcpClient(); Console.WriteLine("User connecting.."); Console.WriteLine("Receiving handshake data.."); data = null; NetworkStream stream = client.GetStream(); int i; while ((i = stream.Read(buffer, 0, buffer.Length)) != 0) { data = System.Text.Encoding.ASCII.GetString(buffer, 0, i); Console.WriteLine("Received handshake data: {0}", data); Console.WriteLine("Processing data.."); // sample handshake: - HANDSHAKE:nick:ip string tempNick = data.Replace("HANDSHAKE:", ""); string[] userDetails = tempNick.Split(':'); // should store to 0:nick, 1:ip Console.WriteLine("Received client nick: {0}", userDetails[0]); Console.WriteLine("Received client IP: {0}", userDetails[1]); break; } Thread.Sleep(1100); // sleep buffer = System.Text.Encoding.ASCII.GetBytes(responseHandshake); Console.WriteLine("Sending response handshake.."); stream.Write(buffer, 0, buffer.Length); } 

Is there a way to make the server accept multiple connections at once, and maintain them? And is there a way to make the client receive multiple messages at once and type while refreshing the messages?

1
  • 1
    There are more ways: 1) Using threads 2) Using polling (iterating through all connected sockets and asking, if there are any data waiting) Commented Nov 11, 2013 at 9:56

1 Answer 1

1

You need to look at using threading (Task library, async/await) to do what you want. Try looking here:

https://codereview.stackexchange.com/questions/29000/c-console-chat-server-async-await-tcpclient-tcplistener-networkstream-asyn

To get you started, assuming the logic in your code is correct you want to split up the server/client, something like this:

static void RunServer() { List<string> clientIP = new List<string>(); List<string> clientNicks = new List<string>(); string responseHandshake = "hello"; Int32 serverPort = 1336; IPAddress machineIP = IPAddress.Parse(GetIP()); Console.Clear(); Console.WriteLine(" - Starting IlanChat server on IP {0}", machineIP); TcpListener server = null; server = new TcpListener(machineIP, serverPort); server.Start(); Byte[] buffer = new Byte[256]; String data = null; Console.WriteLine("Successfully started IlanChat server!"); while (true) // first alpha - only one user at a time { Console.WriteLine(); Console.WriteLine("Waiting for connections.."); TcpClient client = server.AcceptTcpClient(); Task.Run(() => RunClient(client)); } } static void RunClient(TcpClient client) { Byte[] buffer = new Byte[256]; Console.WriteLine("User connecting.."); Console.WriteLine("Receiving handshake data.."); String data = null; string responseHandshake = "hello"; NetworkStream stream = client.GetStream(); int i; while ((i = stream.Read(buffer, 0, buffer.Length)) != 0) { data = System.Text.Encoding.ASCII.GetString(buffer, 0, i); Console.WriteLine("Received handshake data: {0}", data); Console.WriteLine("Processing data.."); // sample handshake: - HANDSHAKE:nick:ip string tempNick = data.Replace("HANDSHAKE:", ""); string[] userDetails = tempNick.Split(':'); // should store to 0:nick, 1:ip Console.WriteLine("Received client nick: {0}", userDetails[0]); Console.WriteLine("Received client IP: {0}", userDetails[1]); break; } Thread.Sleep(1100); // sleep buffer = System.Text.Encoding.ASCII.GetBytes(responseHandshake); Console.WriteLine("Sending response handshake.."); stream.Write(buffer, 0, buffer.Length); } 
Sign up to request clarification or add additional context in comments.

2 Comments

My client and server are in separate projects - I'll look into the threading. Thanks!
Sorry, when I say split up server and client I mean the part that talks to the client on the server side. All I've done is refactored that part of your server code into a different method and added a task so the server can spawn clients without blocking

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.