Member Avatar for GermanD

Hi,
i need some help please on creating a chat app in VS2005. this can be very plain its liker a one to one chat app via internet.
this is my code i have thus far pls tell if im on the right track:
oh and i wrote this so you chat with yourself first this is only temporarily tho and then i need to figure it out how to get it working for two people lol

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.ComponentModel;
using System.Net;
using System.Drawing.Drawing2D;

namespace MyTalk
{
    public partial class Chat : DevComponents.DotNetBar.Office2007Form
    {
        
        private TcpClient objClient;
        private Thread thdListener;
        private TcpListener objListener;
        private string strFriend;
        private string strMe;

        IPAddress ipadd;
        public delegate void Invoker(String t);

        public Chat()
        {
            strFriend = "10.0.1.166";
            ipadd = Dns.GetHostEntry(strFriend).AddressList[0];
            strMe = "Me";

            thdListener = new Thread(new ThreadStart(this.Listen));
            thdListener.Start();

            InitializeComponent();
        }

        private void Listen()
        {
            string strTemp = "";
            objListener = new TcpListener(ipadd,1000);
            objListener.Start();
            do
            {
                TcpClient objClient = objListener.AcceptTcpClient();
                StreamReader objReader = new StreamReader(objClient.GetStream());
                while (objReader.Peek() != -1)
                {
                    strTemp += Convert.ToChar(objReader.Read()).ToString();
                }
                object[] objParams = new object[] { strTemp };
                strTemp = "";
                this.Invoke(new Invoker(this.ShowMessage), objParams);
            } while (true != false);
        }

        private void ShowMessage(String t)
        {
            rtbMessage.Text += strFriend + ": " + t + "\n";
        }

        private void btExit_Click(object sender, EventArgs e)
        {
            objListener.Stop();
            Application.Exit();
            Environment.Exit(0);            
        }

        private void btSend_Click(object sender, EventArgs e)
        {
            rtbMessage.Text += strMe + ": " + rtbType.Text + "\n";
            objClient = new TcpClient(strFriend, 1002);
            StreamWriter w = new StreamWriter(objClient.GetStream());
            w.Write(rtbType.Text + "\n");
            w.Flush();
            objClient.Close();
            rtbType.Text = "";            
        }

Hi,
i need some help please on creating a chat app in VS2005. this can be very plain its liker a one to one chat app via internet.
this is my code i have thus far pls tell if im on the right track:
oh and i wrote this so you chat with yourself first this is only temporarily tho and then i need to figure it out how to get it working for two people lol

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.ComponentModel;
using System.Net;
using System.Drawing.Drawing2D;

namespace MyTalk
{
    public partial class Chat : DevComponents.DotNetBar.Office2007Form
    {
        
        private TcpClient objClient;
        private Thread thdListener;
        private TcpListener objListener;
        private string strFriend;
        private string strMe;

        IPAddress ipadd;
        public delegate void Invoker(String t);

        public Chat()
        {
            strFriend = "10.0.1.166";
            ipadd = Dns.GetHostEntry(strFriend).AddressList[0];
            strMe = "Me";

            thdListener = new Thread(new ThreadStart(this.Listen));
            thdListener.Start();

            InitializeComponent();
        }

        private void Listen()
        {
            string strTemp = "";
            objListener = new TcpListener(ipadd,1000);
            objListener.Start();
            do
            {
                TcpClient objClient = objListener.AcceptTcpClient();
                StreamReader objReader = new StreamReader(objClient.GetStream());
                while (objReader.Peek() != -1)
                {
                    strTemp += Convert.ToChar(objReader.Read()).ToString();
                }
                object[] objParams = new object[] { strTemp };
                strTemp = "";
                this.Invoke(new Invoker(this.ShowMessage), objParams);
            } while (true != false);
        }

        private void ShowMessage(String t)
        {
            rtbMessage.Text += strFriend + ": " + t + "\n";
        }

        private void btExit_Click(object sender, EventArgs e)
        {
            objListener.Stop();
            Application.Exit();
            Environment.Exit(0);            
        }

        private void btSend_Click(object sender, EventArgs e)
        {
            rtbMessage.Text += strMe + ": " + rtbType.Text + "\n";
            objClient = new TcpClient(strFriend, 1002);
            StreamWriter w = new StreamWriter(objClient.GetStream());
            w.Write(rtbType.Text + "\n");
            w.Flush();
            objClient.Close();
            rtbType.Text = "";            
        }

When you say two people, do you mean exactly two people? or multiple people?

If you just mean two people then all you have to do is simply repeat what you have already done.

Create a new project and begin making the client, use TcpClient, the first parameter is the IP Address of the server, and the second parameter is the port that the server is running on.

I have recently finished creating a multiplayer noughts and crosses game that runs over a network using TcpListener and TcpClient objects.

The thing what puzzled me was this (even though I have not read through your code throughly so I am too sure). Why have you created a new TcpClient object in the btSend_Click() method: -

objClient = new TcpClient(strFriend, 1002);

If this is the server application your coding you should only need one TcpClient object per client, this is the TcpClient object returned from the AcceptTcpClient() method.

Likewise if your coding the client you should only need one TcpClient object to connect to the server, this can be created straight by using the TcpClient class etc, there is no need to return the object from the AcceptTcpClient() method, if you get what I mean.

Basically the server has one extra process and that is using the TcpListener, after that has been coded, the code for the server is pretty much the same as the client because you have your TcpClient objects. Its just the case that when your coding the server you get the TcpClient object from the AcceptTcpClient() method, and when your coding the client you get it straight from creating a TcpClient object "new TcpClient()" etc.

Member Avatar for GermanD

Hi there Barnz,
Thanks for the reply and help i will look into detail of everything you said thanks alot.
I have just a few points that i would like to mention and please correct me if im wrong.
i mean exactly two people thats it only a private chat app for my friend that stays in a different country and myself.
Actually i am creating here the client side and the "server side". i dont have a seperate server app. as you can see i have the tcplistener coded in here aswell, this app needs to be only direct communication, i dont know if this is possible though.

the reason for creating a new tcpclient object is:
The first parameter of the constructor is the IP address of my friend im going to talk to. In this case, im talking to myself, so i use the standard IP address that points to my local computer. so for everytime me or my friend sends a message its creates a new tcpclient for the message to send to the specified ip and port.

hope thats makes sense lol, anyway im kinda stuck but i will see what else i can do.

Hi there Barnz,
Thanks for the reply and help i will look into detail of everything you said thanks alot.
I have just a few points that i would like to mention and please correct me if im wrong.
i mean exactly two people thats it only a private chat app for my friend that stays in a different country and myself.
Actually i am creating here the client side and the "server side". i dont have a seperate server app. as you can see i have the tcplistener coded in here aswell, this app needs to be only direct communication, i dont know if this is possible though.

the reason for creating a new tcpclient object is:
The first parameter of the constructor is the IP address of my friend im going to talk to. In this case, im talking to myself, so i use the standard IP address that points to my local computer. so for everytime me or my friend sends a message its creates a new tcpclient for the message to send to the specified ip and port.

hope thats makes sense lol, anyway im kinda stuck but i will see what else i can do.

Hmm, about the new TcpClient object for every message. You should not need to create a new one for everyone message, after it has been created you just use the streams to send and receive data. So after your intial TcpClient object you create there should be no need to create anymore.

Just use your: -

private TcpClient clientobj;

Which you have done in your class, but I mean literally use it, there should only be one.

Alright also, do you know that the TcpListener is only used for listening to connections from clients, not actually listening for chat messages etc? You use your streams for sending and recieving data like chat messages etc. Here are some examples: -

SERVER PROGRAM

TcpListener server = new TcpListener(6060);

The TcpListener listens for incoming connections from clients, sometimes a first parameter may be needed, this is the local address and NOT the clients address. So sometimes it maybe like this: -

TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 5050);

Next use the start() method to start listening for incoming connections: -

server.Start();

Next use the AcceptTcpClient() method which will return a TcpClient object when a client connects: -

TcpClient clientobj = server.AcceptTcpClient();

Right ok, thats a solid connection now, between two TcpClient objects because the client will have been accepted.

Basically from here on in, the client and the server are pretty much the same, you will have TcpClient object, and so will the client his / her self.

To send and recieve data create some streams: -

Network stream = clientobj.GetStream();
StreamReader input = new StreamReader(stream);
StreamWriter output = new StreamWriter(stream);

Then you can do, ReadLine(); and WriteLine(); etc: -

input.ReadLine(); // Reads data from the client.
output.WriteLine(); // Sends data to the client.

CLIENT PROGRAM

The client program is the practically the same as the server, accept instead of using a TcpListener to listen for incoming connections (because there is no need only the server does this) it uses TcpClient directly like so: -

TcpClient clientobj = new TcpClient("255.255.255.FakeIp", 5050);

The first parameter in the TcpClient constructor is the servers ip followed by the port the server is running on, which is the port you set in the TcpListener constructor in the "server program".

Next create the streams, like was done on the server: -

Network stream = clientobj.GetStream();
StreamReader input = new StreamReader(stream);
StreamWriter output = new StreamWriter(stream);

Then you can do, ReadLine(); and WriteLine(); etc: -

input.ReadLine(); // Reads data from the server.
output.WriteLine(); // Sends data to the server.

Hope this helps, basically you should have 1 TcpClient object per program in your case, because none of programs need to accept connections from multiple clients. A pair of TcpClient objects is like a solid connection between client and server etc. One of the programs must act as a server, whether its the same or not, one has to make the connection to the other (client) and one has to recieve a connection from another (server).

In your code I noticed you have strFriend, put into the TcpListener.

The TcpListener should have the local address not the remote address.

Ok I took the liberty of whipping up a quick chat console application, its very simple but it works. I have not added any of the try catch things in either.

ChatApp.cs
This is the main program

using System;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace ChatApp
{
	class ChatApp
	{
		[STAThread]
		static void Main(string[] args)
		{
			Console.WriteLine("SERVER / CLIENT");
			string option = Console.ReadLine();

			if(option == "SERVER")
			{
				new ChatApp().startServer();
			}
			else if(option == "CLIENT")
			{
				Console.Write("Enter Server IP: ");
				new Person(new TcpClient(Console.ReadLine(), 5050));
			}
	}

		public void startServer()
		{
			TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 5050);
			server.Start();
			Console.WriteLine("Server has started.....");
			TcpClient clientobj = server.AcceptTcpClient();
			Console.WriteLine("Client has connected.....");
			new Person(clientobj);
		}
	}
}

Person.cs
This is a class that is part of the ChatApp etc, "Add Item" class file etc.

using System;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;

namespace ChatApp
{
	public class Person
	{
		private NetworkStream theStream;
		private StreamReader theInput;
		private StreamWriter theOutput;

		public Person(TcpClient clientobj)
		{
			Console.WriteLine("Chat started, start chatting!");
			theStream = clientobj.GetStream();
			theInput = new StreamReader(theStream);
			theOutput = new StreamWriter(theStream);

			Thread listenThread = new Thread(new ThreadStart(listen));
			listenThread.Start();

			while(true)
			{
				theOutput.WriteLine(Console.ReadLine());
				theOutput.Flush();
			}
		}

		public void listen()
		{
			while(true)
			{
				Console.WriteLine(theInput.ReadLine());
			}
		}
	}
}

In this example the server surports one connection and that is from the client.

If you want it to support multiple clients then put the TcpListener into an infinite loop in another thread etc.

Member Avatar for GermanD

Hi there and thank you so much for your help.
I have been playing around with your console app and am trying to write it as a windows application. im sitting with onw problem though which is that the form doesnt show when i start as the server. the debugging stops at the line
TcpClient clientobj = server.AcceptTcpClient();
now i know this happens because because my ap is waiting for incoming clients. but how can i like idle my app while it accepts a client and be able to see the form and then just wait for an incoming client?

Im sorry i must sound like such a newbie its just im struggling to get this part of programming :-0
i have learned alot though thanks
this is my code so far for my windows app and i dont care bout the rest yet its just what happoens when i start the server which i have problems with.

private void Form1_Load(object sender, EventArgs e)
        {
            if (myParser.Option == "SERVER")
            {
                btnStart.Visible = true;
                
            }
            else if (myParser.Option == "CLIENT")
            {
                string t = "192.168.0.10";
                //txtMessages.Text += "Enter Server IP: ";
                Person(new TcpClient(t.ToString(), 5050));
            }
        }

        public void startServer()
        {
            TcpListener server = new TcpListener(IPAddress.Parse("192.168.0.10"), 5050);
            server.Start();
            txtMessages.Text += "Server has started.....";

            TcpClient clientobj = server.AcceptTcpClient();
            txtMessages.Text += "Client has connected.....";
            Person(clientobj);
        }

        public void Person(TcpClient clientobj)
		{
			txtMessages.Text += "Chat started, start chatting!";
			theStream = clientobj.GetStream();
			theInput = new StreamReader(theStream);
			theOutput = new StreamWriter(theStream);

			Thread listenThread = new Thread(new ThreadStart(listen));
			listenThread.Start();

			while(true)
			{
                txtMessages.Text += Console.ReadLine().ToString();
				theOutput.Flush();
			}
		}

		public void listen()
		{
			while(true)
			{
				txtMessages.Text += theInput.ReadLine().ToString();
			}
		}

        private void btnStart_Click(object sender, EventArgs e)
        {
            this.startServer();
        }

What form is not showing?

Do you have one form, with a textbox for IP, a textbox for server messages etc, and a button that starts the server.

I do not understand what you mean? The form should already be showing.

How many forms do you have?

when i start the server which i have problems with

You need to create a button that starts the server. That way you can start it after GUI loads and you can use the same form for the client. Just add another button that connects to the server and then have it prompt you for the IP address. Then one program does both the server and the client, just like Barnz's awesome AIM dos version.:cheesy:

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.