A step by step tutorial teaching you how to create your own chat client and chat server easily in C#, for local networks or the Internet.
A C# tutorial showing you how to make use of WMI to extract information on disk drives, such as model, capacity, sectors and serial number.
This tutorial will teach you how to calculate the shipping cost based on the weight, height, length and depth of the box, the distance and the UPS service type.
Creating a Rich Text Editor using JavaScript is easier to do than you might think, thanks to the support of modern browsers; this tutorial will walk you through it.
C# Chat: Part 2 - Building the Chat ServerIn this two part tutorial you will learn how to create a chat client that connects to a chat server and exchanges messages with all the other connected clients. This second part covers the development of the chat server. |
On Saturday, October 20th 2007 at 04:41 PM By Andrew Pociu (View Profile) ![]() ![]() ![]() ![]() (Rated 4.9 with 39 votes) |
||
|
» C# Chat: Part 1 - Building the Chat Client » C# Chat: Part 2 - Building the Chat Server (currently reading) This is the second part of a tutorial that teaches you how to create a C# chat application. In Part 1 - Building the Chat Client we've looked at how to create the chat application that connects to a chat server, and here we now look at how to build the chat server. The Chat ServerThe Chat Server application is a tad more complex than the Chat Client application because it needs to hold information on all the connected clients, await for messages from each and send incoming messages to all. I commented all the code so hopefully you won't have any problems figuring it out without much commentary on the side from me. Fire up a new instance of Visual Studio 2005 and in a new Windows Application project draw the following form:![]() The only controls we are interested in are the two TextBoxes (txtIp and txtLog) and the btnListen button. The IP address inside txtIp is the one where you want your chat server to be listening for incoming connections. You should use your local IP address, which if you're not in a network it could be 192.168.0.1, but it's best that you check using the ipconfig /all command in the MS-DOS Command Prompt window. The multi-line TextBox will hold information about connected clients and the messages that they are exchanging. In the code view, start with the following using statements: using System.Threading; using System.Net; using System.Net.Sockets; using System.IO; Move inside the class and declare a delagate which we will need in order to update the txtLog TextBox from another thread : private delegate void UpdateStatusCallback(string strMessage); Double-click the Start Listening button and you should arrive to it Click event. Have the event handler look like this: private void btnListen_Click(object sender, EventArgs e) { // Parse the server's IP address out of the TextBox IPAddress ipAddr = IPAddress.Parse(txtIp.Text); // Create a new instance of the ChatServer object ChatServer mainServer = new ChatServer(ipAddr); // Hook the StatusChanged event handler to mainServer_StatusChanged ChatServer.StatusChanged += new StatusChangedEventHandler(mainServer_StatusChanged); // Start listening for connections mainServer.StartListening(); // Show that we started to listen for connections txtLog.AppendText("Monitoring for connections...\r\n"); } A couple of objects are being instantiated, including a ChatServer object. We will write the ChatServer class very soon, and you will see that it handles all the incoming connections. In turn, it will make use of another class that we will write, called Connection. The next thing we do is to set up an event handler for the StatusChanged event, which is a custom event that we're going to write very soon. It will inform us when a client has connected, a new message has been received, a client has disconnected, etc. Finally the StartListening() method tells the ChatServer object to start listening for incoming connections. Believe it or not, there are only a few more lines of code to go in this class. One of them is the event handler that we hooked earlier, and the other is the UpdateStatus() method that gets called when an update needs to be made to the form. It's needed because we use Invoke() and the delegate we created earlier to make a cross-thread call (since the ChatServer will be working in a different thread): public void mainServer_StatusChanged(object sender, StatusChangedEventArgs e) { // Call the method that updates the form this.Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { e.EventMessage }); }
private void UpdateStatus(string strMessage) { // Updates the log with the message txtLog.AppendText(strMessage + "\r\n"); } And we're done. Done with the Form1 class, of course. You should now create another file (I called mine ChatServer.cs) and inside it make sure you have all these using statements: using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; using System.Collections; We'll need to use an event that notifies the form class when a new client has connected, disconnected, sent a message, etc. In order to create our own custom event, we need to first define its arguments. More exactly we want a string argument that tells us what type of event has occured (user has connected, user has disconnected, user x says y, etc..) If you're not familiar with events and delegates you might want to read the Delegates and Events in C# tutorial from a week ago. Here is the class that gets and sets the event arguments: // Holds the arguments for the StatusChanged event public class StatusChangedEventArgs : EventArgs { // The argument we're interested in is a message describing the event private string EventMsg;
// Property for retrieving and setting the event message public string EventMessage { get { return EventMsg; } set { EventMsg = value; } }
// Constructor for setting the event message public StatusChangedEventArgs(string strEventMsg) { EventMsg = strEventMsg; } } Moving on, outside this class we declare the actual delegate for the event handler: // This delegate is needed to specify the parameters we're passing with our event public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e); And now before we actually get to fire this event, we define the ChatServer class, in all its glory. Remember this is the class that we used back in Form1.cs: class ChatServer { // This hash table stores users and connections (browsable by user) public static Hashtable htUsers = new Hashtable(30); // 30 users at one time limit // This hash table stores connections and users (browsable by connection) public static Hashtable htConnections = new Hashtable(30); // 30 users at one time limit // Will store the IP address passed to it private IPAddress ipAddress; private TcpClient tcpClient; // The event and its argument will notify the form when a user has connected, disconnected, send message, etc. public static event StatusChangedEventHandler StatusChanged; private static StatusChangedEventArgs e;
// The constructor sets the IP address to the one retrieved by the instantiating object public ChatServer(IPAddress address) { ipAddress = address; }
// The thread that will hold the connection listener private Thread thrListener;
// The TCP object that listens for connections private TcpListener tlsClient;
// Will tell the while loop to keep monitoring for connections bool ServRunning = false;
// Add the user to the hash tables public static void AddUser(TcpClient tcpUser, string strUsername) { // First add the username and associated connection to both hash tables ChatServer.htUsers.Add(strUsername, tcpUser); ChatServer.htConnections.Add(tcpUser, strUsername);
// Tell of the new connection to all other users and to the server form SendAdminMessage(htConnections[tcpUser] + " has joined us"); }
// Remove the user from the hash tables public static void RemoveUser(TcpClient tcpUser) { // If the user is there if (htConnections[tcpUser] != null) { // First show the information and tell the other users about the disconnection SendAdminMessage(htConnections[tcpUser] + " has left us");
// Remove the user from the hash table ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]); ChatServer.htConnections.Remove(tcpUser); } }
// This is called when we want to raise the StatusChanged event public static void OnStatusChanged(StatusChangedEventArgs e) { StatusChangedEventHandler statusHandler = StatusChanged; if (statusHandler != null) { // Invoke the delegate statusHandler(null, e); } }
// Send administrative messages public static void SendAdminMessage(string Message) { StreamWriter swSenderSender;
// First of all, show in our application who says what e = new StatusChangedEventArgs("Administrator: " + Message); OnStatusChanged(e);
// Create an array of TCP clients, the size of the number of users we have TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count]; // Copy the TcpClient objects into the array ChatServer.htUsers.Values.CopyTo(tcpClients, 0); // Loop through the list of TCP clients for (int i = 0; i < tcpClients.Length; i++) { // Try sending a message to each try { // If the message is blank or the connection is null, break out if (Message.Trim() == "" || tcpClients[i] == null) { continue; } // Send the message to the current user in the loop swSenderSender = new StreamWriter(tcpClients[i].GetStream()); swSenderSender.WriteLine("Administrator: " + Message); swSenderSender.Flush(); swSenderSender = null; } catch // If there was a problem, the user is not there anymore, remove him { RemoveUser(tcpClients[i]); } } }
// Send messages from one user to all the others public static void SendMessage(string From, string Message) { StreamWriter swSenderSender;
// First of all, show in our application who says what e = new StatusChangedEventArgs(From + " says: " + Message); OnStatusChanged(e);
// Create an array of TCP clients, the size of the number of users we have TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count]; // Copy the TcpClient objects into the array ChatServer.htUsers.Values.CopyTo(tcpClients, 0); // Loop through the list of TCP clients for (int i = 0; i < tcpClients.Length; i++) { // Try sending a message to each try { // If the message is blank or the connection is null, break out if (Message.Trim() == "" || tcpClients[i] == null) { continue; } // Send the message to the current user in the loop swSenderSender = new StreamWriter(tcpClients[i].GetStream()); swSenderSender.WriteLine(From + " says: " + Message); swSenderSender.Flush(); swSenderSender = null; } catch // If there was a problem, the user is not there anymore, remove him { RemoveUser(tcpClients[i]); } } }
public void StartListening() {
// Get the IP of the first network device, however this can prove unreliable on certain configurations IPAddress ipaLocal = ipAddress;
// Create the TCP listener object using the IP of the server and the specified port tlsClient = new TcpListener(1986);
// Start the TCP listener and listen for connections tlsClient.Start();
// The while loop will check for true in this before checking for connections ServRunning = true;
// Start the new tread that hosts the listener thrListener = new Thread(KeepListening); thrListener.Start(); }
private void KeepListening() { // While the server is running while (ServRunning == true) { // Accept a pending connection tcpClient = tlsClient.AcceptTcpClient(); // Create a new instance of Connection Connection newConnection = new Connection(tcpClient); } } } Overwhelmed? It's really not that complicated if you take it line by line and read the comments. It starts by defining two hash tables. These two hash tables will hold the username and the TCP connection associated with it. We need two of them because at one point we'll want to retrieve the TCP connection by giving the username, and at some other point we'll want to retrieve the username by giving the TCP connection. The 30 defines how many users the chat server can hold at one given point, but you can easily go into hundreds if needed, without worrying about a performance decrease. The AddUser() method is obvious - it adds a new user to the hash tables, and thus to our list of connected chat clients. The RemoveUser() method does the opposite. The OnStatusChanged will fire the StatusChanged event, which is right now handled inside Form1.cs. Thus, it's our way of updating the form with the latest message from inside this ChatServer object. The SendAdminMessage sends an administrative message to all connected clients. You can see how it loops through the hash table and attempts to send them the message. If the message didn't get through, they probably disconnected and we then remove them. This is very similar to what the SendMessage() method does, only that this time it sends a message from a specific chat client to all the others. The StartListening() method is the one we called inside Form1, and it's the fire starter, the instigator. It defines the first needed objects and starts a new thread that keeps listening for connections, and that is the KeepListening() method. And that's where our story continues, because if you look inside the KeepListening() method you will see we create a new object of type Connection. That's because each user connected to our server will have its own instance of Connection. If there are 10 users currently connected, there will be 10 instances of the Connection object. So let's look at the final class of our chat server: // This class handels connections; there will be as many instances of it as there will be connected users class Connection { TcpClient tcpClient; // The thread that will send information to the client private Thread thrSender; private StreamReader srReceiver; private StreamWriter swSender; private string currUser; private string strResponse;
// The constructor of the class takes in a TCP connection public Connection(TcpClient tcpCon) { tcpClient = tcpCon; // The thread that accepts the client and awaits messages thrSender = new Thread(AcceptClient); // The thread calls the AcceptClient() method thrSender.Start(); }
private void CloseConnection() { // Close the currently open objects tcpClient.Close(); srReceiver.Close(); swSender.Close(); }
// Occures when a new client is accepted private void AcceptClient() { srReceiver = new System.IO.StreamReader(tcpClient.GetStream()); swSender = new System.IO.StreamWriter(tcpClient.GetStream());
// Read the account information from the client currUser = srReceiver.ReadLine();
// We got a response from the client if (currUser != "") { // Store the user name in the hash table if (ChatServer.htUsers.Contains(currUser) == true) { // 0 means not connected swSender.WriteLine("0|This username already exists."); swSender.Flush(); CloseConnection(); return; } else if (currUser == "Administrator") { // 0 means not connected swSender.WriteLine("0|This username is reserved."); swSender.Flush(); CloseConnection(); return; } else { // 1 means connected successfully swSender.WriteLine("1"); swSender.Flush();
// Add the user to the hash tables and start listening for messages from him ChatServer.AddUser(tcpClient, currUser); } } else { CloseConnection(); return; }
try { // Keep waiting for a message from the user while ((strResponse = srReceiver.ReadLine()) != "") { // If it's invalid, remove the user if (strResponse == null) { ChatServer.RemoveUser(tcpClient); } else { // Otherwise send the message to all the other users ChatServer.SendMessage(currUser, strResponse); } } } catch { // If anything went wrong with this user, disconnect him ChatServer.RemoveUser(tcpClient); } } } It doesn't look too complicated, does it? There's the constructor that initializes the TcpClient object, then there's CloseConnection() which is called when we want to get rid of a currently connected client, and finally there's AcceptClient() which checks for the username validity and if all is fine, it adds the user to the hash tables. If anything goes bad, it removes the user. I'll leave you chew on the code for a while now. It's pretty much as easy as it can get for a C# based chat/server application, but that also means it can use more error handling. Also if you have any suggestions to improve the code or to fix a bug, feel free to post a comment below. |
|||
Digg It!
Del.icio.us
Reddit
StumbleIt
Newsvine
Furl
BlinkList
|
|||
|
|||
Current CommentsVery helpful tutorial! Easy explained but a good variety of interesting c# classes...
I only changed the line
tlsClient = new TcpListener(1986);
to
tlsClient = new TcpListener(ipaLocal, 1986);
since this use of the method is deprecated;
I still haven\'t tested it yet, but i found some problems with exception handling, and the server .EXE still runs after exiting the application, but the rest goes well!
oncy i've tried to integrate animations (icons, gifs, anis) into a chat application in c#... but i didn't find out how to solve this... has any one an idea? Thanks
hhhmmm.... something's seriously wrong with the code.
client crashes every time user tries to disconnect. i can't seem to solve this, but it has to do with the threading. also when tcpclient closes, connection stays open. i couldn't find the way to kill it.
server's thread is also runnig after the server windows closes (and stays active till system restart).
any thoughts?
p.s. nevertheless, i think this is one of the best c# sockets tutorials on net so far.
For fixing the server's thread - you should do the same thing that we did for the client in the OnApplicationExit event.
The problem I could reproduce, as the two of you mentioned, is the one where the client crashes when you close it. I'll take care of it and update the tutorial, it's nothing major.
By the way, the server application could be transformed into a service so that it runs in the background. The incoming messages could be written to a log file.
i like this tutorial I have question where is the "e" declaration in
public static void SendAdminMessage(string Message)
{
StreamWriter swSenderSender;
// First of all, show in our application who says what
e = new StatusChangedEventArgs("Administrator: " + Message);
OnStatusChanged(e);
I fixed the client error by changing the:
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
code in private void ReceiveMessages() to:
while (Connected == true)
{
try
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch{}
}
Chryso, does your fix close network stream between client and server?
Excellent tutorial! It filled in a lot of the gaps that I had with some of the networking code required for a project such as this. I plan to address some of the bugs and maybe add a few features here and there to this code. If it ends up being a worth while adventure I will be sure to post my changes here. Keep up the great work!
Unfortunately, this does not convert well over to .Net 3.0. The only part I couldn\'t get to work was the \"this.Invoke\" part. Since, WPF does not use System.Windows.Forms at all. but otherwise, pretty helpful code. thanks.
I followed the first part of this tutorial series as well as this second part exactly, word for word. My code is nearly identical although some of my comments contained additional writing just for myself.
I had absolutely no success in getting it to work. At first, the Client would crash upon clicking the connect button. I followed some suggestions in the other comments, and prevented the client from crashing, but it still never connects. Upon debugging the server one time, VC# Express informed me of something being deprecated, but it went away and I have no idea what it was now.
I thought I was actually learning but apparently I'm not if it doesn't even work - and to my knowledge, the application failure isn't a result of anything I've done. *sigh*, and this tutorial was the best I've found for C#.
Oh well, best of luck to everyone else. Cheers.
Martin,
Your problem is surely something that can be fixed, but you'll need to tell us where does it crash (the exception message, possibly the line number.)
Alright, now that I\'ve gained some more free time to look into this, I\'ve realized now that the client is still crashing, but rather than crashing on-click of the Connect button, it\'s crashing during the process of actually trying to make the connection.
VC# Exp is saying:
\"NullReferenceException was unhandled.
Object reference not set to an instance of an object.\"
It says the above in regards to the following line from the client\'s Form1.cs (which it highlighted):
if (ConResponse[0] == \'1\')
I checked the Part 1 of this tutorial series for that line & mine is exactly as the tutorial\'s. VC# suggests using the \"new\" keyword to create an object instance, but I\'m not necessarily sure I understand what that means... I come from a background of interpreted languages and so I wonder if I\'m just not fully comprehending how objects work in C#, although I thought I had at least \'some\' idea.
hello it is ok
Sorry for my ignorance, but what if I want to deply such an application? Do I need to run a windows box as my webserver, so I can have the server instance of this application running 24/7 and thus be able to serve as the chat server for anyone who connects on their end?
HondaCop - yes, that is correct.
Thanks for the response, Andrei... I got this working and it\'s simply awesome. I will be doing some modifications to it, to suit my needs. I have 2 questions though...
1. How can I convert the ChatServer to run as a windows service?
2. Have you developed another version of this chat system? I am interested in perhaps being able to have 2 more features:
- Ability to send private messages
- Have a list of connected users
Thanks for any help on this, my friend, and THANKS for your contributions. They are greatly appreciated.
Great code! But how to terminate server process after server's window closes??? Server's process still exists ...
Can someone please tell me how to make the Server send the list of connected users to the Client, once he connects?
Thanks in advanced.
Liking this. I solved both client and server thingys and swapped the textbox for a richtext box to bold incoming messages and added a flatfile to store user prefs for ip and username. Neat app and great tut!
Soulice, do you mind sharing your custom code? I would love to be able to solve the crashing problem which occurs when a client is disconnected suddenly.
hi, this is a tutorial with great explanations ans coding. Actually i want to try sending msg from a pc to another on network through the server( it shouldnt be visible to others). what will be the modification that i will have to do in this code.
Thanks ,
I've fixed most of the errors... Except I still can't figure out how to close the frickin' client once the streams are open....
Excellent Tutorial!
Can someone help with closing the server application when the user closes the app? It seems as the thread to listen is still running but I cannot figure it out.
Thanks
hi Andrei,
When the client gets diconnected from Server, the Server crashes and the Debugging pointer points to this line in FORM1.CS :
public void mainServer_StatusChanged(object sender, StatusChangedEventArgs e)
{
// Call the method that updates the form
this.Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { e.EventMessage });
}
Pl help me Dude !!!
hi andrei,
Why are we using 2 hash tables, but both stores the same information.
And how we can add "Themes" facility into our C# windows appln ?
help me ... pl
hi friends,
Why are we using 2 hash tables, but both of these uses the same data to store.
Hi Together
"server's thread is also runnig after the server windows closes (and stays active till system restart)."
Is there a somewhere a solution to this problem?
this is a good example, however, in the first time, i can you it, but now when i run it, it display the error \\\"socketexception was unhandled, so can you help me to fix this problem. thank you so much for your code and for your help.
The reason why the server throws an exception if it should be closen, it is because:
// Create the TCP listener object using the IP of the server and the specified port
tlsClient = new TcpListener(myIP, 1986);
in method public void StartListening()
keeps beeing in an inner thread and can only be stopped by force, as far as I know.
So I used a new method in the form-class:
private void ServerForm_FormClosing(object sender, FormClosingEventArgs e)
{
mainServer.RequestStop();
}
which trys to stop the TcpListener waiting by using this implementation in the server class:
public void RequestStop()
{
if (thrListener != null && thrListener.IsAlive) // thread is active
{
// set event \"Stop\"
tlsClient.Stop();
ServerIsActive = false;
while (thrListener.IsAlive)
{
Application.DoEvents();
}
}
}
So the only thing left is to catch the exception in KeepListening() by:
private void KeepListening()
{
// While the server is running
while (ServerIsActive)
{
try
{
// Accept a pending connection
tcpClient = tlsClient.AcceptTcpClient();
// Create a new instance of Connection
Connection newConnection = new Connection(tcpClient);
}
catch (SocketException e)
{
; // Do nothing
}
}
}
That one fixes it for me..
ups I changed some things already in my code so it may be hard to follow the code:
ServerIsActive is the bool ServRunning
I hope this was all.
am yet to test this tutorial but geekpedia has been helpful. more power to your elbow!
hey guys i included a listbox in the client apllication.i want to populate it with the users hashtable .so how can i do that.
how can i pass a hashtable to a client that is just usernames
Great tutorial! One little thing:
You might change the order of:
if (htConnections[tcpUser] != null)
{
SendAdminMessage(htConnections[tcpUser] " has left us");
ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]);
ChatServer.htConnections.Remove(tcpUser);
}
into:
ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]);
ChatServer.htConnections.Remove(tcpUser);
SendAdminMessage(htConnections[tcpUser] " has left us");
since it produces an unwanted dead-loop in case the connection broke in an unpropper way (The Admin-Message tries to send the Message to a person that no longer exists, which causes in a new removal of the person...
... but you have to store the name of the leaving client first :) into a string first. ouch!
string uname = htConnections[tcpUser].ToString();
htUsers.Remove(htConnections[tcpUser]);
htConnections.Remove(tcpUser);
SendAdminMessage(uname " has left us");
I decided to make network small game in my one lesson.
So i need some help
How to know server's(listening) ipaddress from client
To cancel the thread, you can make it like Alexander mentioned with his RequestStop() method just add this to it:
public void RequestStop()
{
if (thrListener != null
hi all, first off i would like to say that i love this site the only problem is that most of the tutorials are in c# and i program in vb. I tried to convert all of the above code into vb but my program is not working the way it should. it connects fine....but when i send a message it keeps on sending the message the whole time and i end up having to forcefully close my app. any ideas?
could any1 give me a reason as to why c# is better than vb. I'm still rather new to programming and have worked in vb before so it looked like the logical choice.
For a small application like this it's not really necessary which .Net language you use.
You are sending a message from your Client and then what happens?
Does the server get the message ?
IS the client Log box updating?
Is the Server log box updating?
Maybe typo on the ip / port ?
The server is updating and the client but continuously. It looks to me like the app is getting stuck in the sendmessage loop. I might've messed up the event handler for updating the txtLog. but then it wouldn't have updated it at all. I've been going through the debugger but can't see why its not working. I don't know if the StreamReader.readline is suppose to be cleared after the first time the txtbox is updated.
I downloaded the project and it works fine in c#. I'm going to try and switch over to c#. It won't be easy as i'm use to the formatting of vb.
the code is interesting , but when i builde there is Error 'StatusChangedEventArgs' could not be found (are you missing a using directive or an assembly reference?) what is the problem?
andrei da-mi id me mail k vreau sa te intreb ce nu inteleg din cod...
Thank You very very much.......
Your tutorial is exellent
the tutorail is help full. but i need to develop a socket application wich transfer's data in WAN ( b/n two public ip ). so, wich method is best ASynchronous or Synchronous communication in C#. please help me if u can.
thank u
Hi to all
I want to stop the TcpListener when i press a button
I send a boolean value "status" when I change the text button from Start to Stop in constructor of class ChatServer:
bool status = false;
i send the status value
ChatServer mainServer = new ChatServer(ipAddr, lstUsers, status);
In server class is function StartListening()
with this case:
if (sts == true)
{
tlsClient.Start();
ServRunning = true;
thrListener = new Thread(KeepListening);
thrListener.Start();
}
else
{
RequestStop();
}
And the RequestStop() like that:
if (thrListener != null
And the RequestStop() like that:
if (thrListener != null
I want to stop TcpListener
The fucntion is like that posted upper by Alexander
HOW TO SEND THE HASHTABLE WITH USER LIST TO CLIENT?
HELP ANYBODY ...
I have a same problems with TCPServer.AcceptTcpClient()
i changed that code ;
Socket s = TCPServer.AcceptClient();
NetworkStreamns = new NetworkStream(s);
I think TCPClient from AcceptTcpClient() is not thread safe.
Sure this example is very good one to understand the real communication in the client server architecture, also between clients.
Example is absolutely superb, rest of little things can be solved by the programmers.
Thanks for this help.
From a previous post,
"Unfortunately, this does not convert well over to .Net 3.0. The only part I couldn\'t get to work was the \"this.Invoke\" part. Since, WPF does not use System.Windows.Forms at all. but otherwise, pretty helpful code. thanks."
Any ideas how to get the Invoke thing done in .NET 3.0 ??
Hmm I Have This Error Say, Only one usage of each socket address (protocol/network address/port)
is normally permitted, this is my listening code ..
tlsClient = new TcpListener(my pucblic ip hidden, 90);
i checkked if it was opened, and it was not in use, i also port forwrded it =D
Ok I Fixed It (restarted comp) Thing is If you put the server on and then take it off. Then put it on again, then try to connect, you'll get the error
"Only one usage of each socket address (protocol/network address/port)"
Plz anyone help me :(
How Can I make A Clear Logs Button, That clears every log in the server?
plz help thanks
hi friends
the tutorial is good but sorry to say that the code doesnt works as it should.
i have downloaded the application and done exactly as said above but on clicking the start listening button on server it displays error
"Only one usage of each socket address (protocol/network address/port) is normally permitted" on line tlsClient.Start();
i m new to network programing so sorry to say but i cant fix the errors in the code. Can anyone help me in any manner. if anyone can mail me the code without errors then it will be of great help for me to learn network programing concepts.
thanks
hi all
the problem is solved actually if u just change the port number used in our application 1986 to 1980 or any other port which is not used. just try changing the port number it will work.
the code works by changing the port no.
thanks to the site.
I know this is a while after the article was posted, but I just found it so I assume others are just arriving too.
Rather than manually searching for and entering your IP address, try the code below on the form load event. It will place your IP Address in the box for you, just a little time saver.
BTW, this is a great tutorial, exatly what I've been looking for! Thanks!
string strHostName = Dns.GetHostName();
IPHostEntry ipEnt = Dns.GetHostEntry(strHostName);
IPAddress[] addr = ipEnt.AddressList;
txtIp.Text = addr[0].ToString();
Excelente aporte, excelente trabajo, gracias!!! BUEN TRABAJO...
Hi Everybody
Do someone maybe have a working example with error handeling that you possibly can email me - i am very new to c# programming and the network programming is getting me under a bit :( but i am trying very hard to get the hang off it.
Please help me with this. Im trying to debug the program step by step to get the flow of how all works but then get exception errors and then i loose my way :(
And is it possible to convert this into private chats or add it - and where must i begin.
If someone will please help - you can invite me on msn (gholfstok@hotmail.com) I will really apreciate it :P
Thankyou! Thankyou for the AWESOME tutorial/s !
Worked great!
Please i need help with the connect button, i wish to start / stop server just like the client connetc/disconnect
also remain the mistery about connected users list :p
Ok i've made a function to send a message to single client, strTo is the IP of the target-client
public static void SendPrivateMessage(string From, string Message, string strTo)
{
StreamWriter swSenderSender;
e = new StatusChangedEventArgs("To: " strTo " : " Message);
OnStatusChanged(e);
TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
// Loop through the list of TCP clients
for (int i = 0; i < tcpClients.Length; i )
{
if (Message.Trim() == "" || tcpClients[i] == null)
continue;
// we search until we find the same ip for the array tcpClients and strTo
if ((System.Net.IPEndPoint)(tcpClients[i].Client.RemoteEndPoint)).Address.ToString() == strTo)
{
//... the rest is the same of "SendMessage" method
// Send the message to the current user
swSenderSender = new StreamWriter(tcpClients[i].GetStream());
// Try sending a message to each
try
{
// Send the message to the current user in the loop
swSenderSender = new StreamWriter(tcpClients[i].GetStream());
swSenderSender.WriteLine(From ":" Message);
swSenderSender.Flush();
swSenderSender = null;
}
catch // If there was a problem, the user is not there anymore, remove him
{
RemoveUser(tcpClients[i]);
}
Ok i've made a function to send a message to single client, strTo is the IP of the target-client
public static void SendPrivateMessage(string From, string Message, string strTo)
{
StreamWriter swSenderSender;
e = new StatusChangedEventArgs("To: " strTo " : " Message);
OnStatusChanged(e);
TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
// Loop through the list of TCP clients
for (int i = 0; i < tcpClients.Length; i )
{
if (Message.Trim() == "" || tcpClients[i] == null)
continue;
// we search until we find the same ip for the array tcpClients and strTo
if ((System.Net.IPEndPoint)(tcpClients[i].Client.RemoteEndPoint)).Address.ToString() == strTo)
{
//... the rest is the same of "SendMessage" method
// Send the message to the current user
swSenderSender = new StreamWriter(tcpClients[i].GetStream());
// Try sending a message to each
try
{
// Send the message to the current user in the loop
swSenderSender = new StreamWriter(tcpClients[i].GetStream());
swSenderSender.WriteLine(From ":" Message);
swSenderSender.Flush();
swSenderSender = null;
}
catch // If there was a problem, the user is not there anymore, remove him
{
RemoveUser(tcpClients[i]);
}
well..i found some errors in that "SendPrivateMessage"
like WriteLine(From ":" Message); use a " " to put them toghether...
i found a weird Error....
i clicked CONNECT (client side)
quickly several times... and.. if i click CONNECT before the Server note this... it will crash...
i dont know how can i solve it...
¿any ideas?
you might try to enable the button until the point where the connection is made.
sorry i've made some mess but the sense should be clear ^_^
actually on my project i've made a function, which try connect on start, if it will fail will wait for 5 second and then it will retry in in loop..
works pretty fine.
Great tutorial. How can you scale the chat server? Say if you have so many clients that you need two servers (A
(Sorry, my previous comment got truncated.) Great tutorial. How can you scale the chat server? Say if you have so many clients that you need two servers (A and B) to handle all the client connections. How does client X on server A talk to client Y on server B? Many thanks!
Hello,
thanks for your tutorial, its really great!
But I've a problem with stopping the server: The server quits fine if no clients were ever connected to but if one client is/was connected, the server does not exit anymore! There is still a task running which has to be cancelled manually.
I haven't yet figured out what the problem is. I tried the solution in the comments, but it does not help. Any ideas?
What do I need to chat with someone over the Internet?
What IP address do I have to provide the other person to connect to me?
Does this program supports it?
I think, I found the problem with the server.
When you stop the server it removes the clients from the hashtable. That's ok, but this code:
while ((strResponse = srReceiver.ReadLine()) != "")
{
if (strResponse == null)
{
ChatServer.RemoveUser(tcpClient);
}....
in the AcceptClient() method will loop forever. So I added a bool to the class and changed the RemoveUser() method to:
// New bool for class:
private bool _StayInWhileLoop = true;
public static bool RemoveClient(TcpClient tcpUser)
{
if (htConnections[tcpUser] != null)
{
ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]);
ChatServer.htConnections.Remove(tcpUser);
return true;
}
else
return false;
}
I also changed the loop to:
while ((_sResponse = _oStreamReceive.ReadLine()) != ""
while ((_sResponse = _oStreamReceive.ReadLine()) != ""
ARGH! Why is this always truncated when it starts to geht interesting :-)
AND AND)<- replace this with the and-sign _StayInWhileLoop)
{
if (_sResponse == null)
{
_StayInWhileLoop = ChatServer.RemoveClient(_oTCPClient);
}
else
ChatServer.CheckReceivedCommand(_sCurrentUser, _sResponse);
}
This seems to work properly.
i'am at vietnam , i'm study IT at the hutech universty viet nam
i very much author' article "Chatserver and Chatclient" who this wirtten !
i'am at vietnam , i'm study IT at the hutech universty viet nam
i very much thank about author' article "Chatserver and Chatclient" who this wirtten !
Great TuT. Gave me a nice introduction into the world of networking!
hello sir. let's say the client is already connected to the server. when i try closing the client from the taskbar and ends the client's process, the server crashes. could you help me with my problem. thanks
Fantastic, at last a handy tutorial thats simple and actually works
It almost pasted straight in although i did recieve the 'deprecated' error, when i noticed the comment on this feedback with a resolution it worked :)
Will need tweaking for my specific purposes but its a fantastic start
Well done and cheers
ldsmg;l
hey guys... this is a good tutorial actually .. but i got an error whl closing the application . i saw the solution up above.. it is really hard 4 me 2 follow.. then
i just simply catch the error using IO exception then its work! :D
by budAk FsKtm o4
THanks for sharing. :) This helps me a lot. Keep it up
I got the error inthis line thrListener = new Thread(KeepListening);
thrListener.Start();
here KeepListening needs () .plz help me..
I got the error inthis line thrListener = new Thread(KeepListening);
thrListener.Start();
here KeepListening needs () .plz help me..
I got the error inthis line thrListener = new Thread(KeepListening);
thrListener.Start();
here KeepListening needs () .plz help me..
I have everything working all but 1 thing.
When there are users connected to the server and the server service or app is closed.. the users are still actually connected to the server. and therefore the form of the server actually closes but the thread stays open. If I hit disconnected on ALL the clients then the server process will close. How can i disconnected all the clients on Server Form Close?
//keep listening
try
{
//code
}
catch(IO Exception err)
{
//do nothing
}
dat one is fixed for me..
ellow..i'm try to build the real time chat program using C# for my research. So,first ,I need to build simple chat program using C#. Im try fellow all the tutorial above but its not working. BUt when i tried the sample its worked. Can anybody help me how to fix it. If anyone have the completed code can share wif me?
Hi, Thanx for greate tutorial.
When i use local ip addresses i can send and recieve data but when i use wan ip addresses clients are not working. What is the reason of that ? And can i fix it ?
Thanx.
hi
There're much samples how to work with tcp/ip via c#. But this article is exellent and full.
a great thanks
I just saw this ... it's a wonderful tutor. Hats-off for a wonderful work done
I just saw this ... it's a wonderful tutor. Hats-off for a wonderful work done
I just saw this ... it's a wonderful tutor. Hats-off for a wonderful work done
I just saw this ... it's a wonderful tutor. Hats-off for a wonderful work done
Thx for sharing with everybody.
If I can plz make few small suggestions:
How about making all messages from Administrator appear in Grey color???
How about assigning random color to the User's messages?
How about providing a list of active users in the Client window? I know this requires lot of work like updating the list everytime a user enters'/exist's. But this one is really required I feel.
I'm sure that will enhance the experience. :)
Hi, very good tutorial and code. Much appreciated.
I have a question, I want to host this, the server.
I want people to be able to connect to it with the chat client, I'm stuck behind a NAT/router firewall, what port must I use to port forward for the server, so people can connect?
Thanks
hi
thank you for this wonderful article, I have a question about private chat (person to person)
how can i make a private chat? actually i can handle in server side but i can not handle in client side.
The problem is , i can't detect which window must read the incoming message from Server.It means when i opened 2 windows, one for public chat room and another windows for p2p chat, both of them are listing to the server at the same time, and i dont know how should i handle incoming message.
thank you
In the RequestStop() proposed by another user, you should consider adding the line 'thrListener.Abort();' before 'tlsClient.Stop();', so that it doesn't throw the error "A blocking operation was interrupted by a call to WSACancelBlockingCall". That is, you should be closing the thread before closing the socket.
Hm, though that'll only cancel one thread and then your program won't exit properly. A better alternative would be to make the threads background threads, so that the program won't hang. So add 'thrSender.IsBackground = true;' before 'thrSender.Start();'.
Since I use RequestStop() before terminating the entire program or disconnecting, I'd also add something like 'tcpClient.Close();', so that all the clients know they're being disconnected from the server (for this you'll need to loop through the hashtable and close them one by one).
Another bug, the while loop should not be doing this: '((strResponse = srReceiver.ReadLine()) != "")'. You'll get the WSACancelBlockingCall error if you try to close the connection because it's still expecting to receive something when it may actually be closed. Instead, change the while loop to check if the program is still running, and then put an 'if' statement inside with '(!string.IsNullOrEmpty(strReceive = srReceiver.ReadLine()))' where you can nest the rest of the stuff.
I'm having trouble implementing Max's private message method, your passing strTo , into the server, what do you do to pass that extra string along with the StrMessage to the server...
thanx
Hi all,
What part should be changed after I've downloaded the complete original version for client and server files. When i open up the server --> start listening followed by opening up the client and click connect, I get -->
Socket exception was unhandled for this part:
"tcpServer.Connect(ipAddr, 1986);"
thanks in advance ^.^
Those of you having issues with the server process not closing, here is an easy way to fix it:
In the Form.cs, make the variables ipAddr and mainServer static , and declare them at the top of the class.
Then in the Start Listening event handler initialize the variables if they are null
Then make a property in ChatServer that lets you see if you are currently listening. If so (meaning you want to disconnect) call a new function inside of ChatServer called StopListening or something similar that aborts the listener thread
Hi Hi,
Wow .. its a really nice application. Thanks for sharing... I am new to C#, your article really inspired me. Can you send me the project please(my mail is neutralfox <at> gmail
<dot> com).
Thanks a lots in advance.
Regards,
Mike
Hi all, awsome tutorial! if anyone is looking for an alternitive have a look at lidgren-network project
Thanks so much dude, iv been looking for an example c# client/server application for a while and yours has by far been the best find.
Thanks again :D
Yem
I downloaded the sources and tried the client. When I try and Disconnect. The client still crashes. When do you plan on added the fix for this.
Hi!
I have a problem in the server. When a user log out from the server there is an exception in the UserRemove methode. It's an ArgumentNullException in the hash table. (Server.htUsers.Remove(Server.htConnections[tcpUser]);)
The problem is that the key is set by null value.
Do you know anything about that?
Hi!
I have exactly the same problem as you.
I solved it by doing this in Client :
private void SendMessage()
{
if (txtMessage.Lines.Length >= 1)
{
string text = txtMessage.Text;
text = text.TrimStart(null);
text = text.TrimEnd(null);
swSender.WriteLine(text);
swSender.Flush();
txtMessage.Lines = null;
}
txtMessage.Text = "";
}
Hi.. thank for your helpfull tutorial..
I want to ask..how I can send online users to all the clients by using another listbox1 on client side..
could you help me please!! at least give me some ideas...
thx again...
Thank you for this wonderful tutorial and collection of comments. I don't know what I would have done without it!!!
Can any1 mail me the completely working well program.
Since I see that there has been many corrections done !!!!
Can any1 care to mail it to me.
thnx.
Why did you do the hashtables as static objects?
Wouldn't it be better to use Singleton design pattern
Excellent Tutorial! I wanted to use this with Flash. I get some odd behavior. I can open a socket with flash and establish a connection. The server and client both report "User x has joined us" but only reports "User x says:". I've altered the outbound message to report the message.length and the count reports the proper string length. I thought maybe I was using the wrong encoding, but the name comes through so why not the message? Any suggestions would be greatly appreciated...what's left of my hair Thanks you. :)
James
thanks !! very good article.
Server consume all memory and need to reboot after 100 messages transfer from clients to server and vice versa.
Any suggestion guys !!
great article but code not written properly
Hey this really is a great tutorial!
Anyway, I wonder how could I display the connected users (hastable) to clients to establish a private messaging? And how to use the SendPrivateMessage function given by one of our friends here?
Your replies are very much appreciated! Thanks again. Keep up. ^^
Hey this really is a great tutorial!
Anyway, I wonder how could I display the connected users (hastable) to clients to establish a private messaging? And how to use the SendPrivateMessage function given by one of our friends here?
Your replies are very much appreciated! Thanks again. Keep up. ^^
Hey this really is a great tutorial!
Anyway, I wonder how could I display the connected users (hastable) to clients to establish a private messaging? And how to use the SendPrivateMessage function given by one of our friends here?
Your replies are very much appreciated! Thanks again. Keep up. ^^
Hey this really is a great tutorial!
Anyway, I wonder how could I display the connected users (hastable) to clients to establish a private messaging? And how to use the SendPrivateMessage function given by one of our friends here?
Your replies are very much appreciated! Thanks again. Keep up. ^^
Hey this really is a great tutorial!
Anyway, I wonder how could I display the connected users (hastable) to clients to establish a private messaging? And how to use the SendPrivateMessage function given by one of our friends here?
Your replies are very much appreciated! Thanks again. Keep up. ^^
Hi Andreu,
Very Nice Tutorial for Beginner's of network Programming,
Wish you all the Success Ahead,
Thanks for giving such a Nice Article which helped to a Great Extent for People Like me
Rajesh
thankyou....it was helpful
thankyou :)
Has anybody figured out how to fully close the server after a client has connected to the server? The server is still hanging for me.
How to stop the server from Listening
Pls reply early Its Urgent
Thank you very much for your help!!
Thank you very much for your help!!
can anyone send me the complete working code? i still have a problem with the hanging server. thx
@Andrei (and others willing to listen):
I used your code to make my own chat-application. I changed it with these additions:
1) The client has a clientlist that updates via events
2) The server can start/stop server with a button
3) The server has a clientlist that updates via events
4) The server can send messages to all connected clients
5) The server can send personal messages to a client
6) The server can kick(remove) a client
7) The server has a custom build progressbar indicating the amount of connected clients
8) Original threading code has been replaced with backgroundworkers
I would be happy to share my code if there is a need for it.
Owh btw. I fixed the nasty bugs when the client and server exits. I also fixed the TCP connection bugs mentioned earlier, connections get opened and closed like they should.
I'll be waiting for a reaction.
Yours sincerely,
A happy programmer from Holland :)
I would love to see the code.
I would love to see the code.
Yes. I think there would be a lot of programers that would love to have it. Please send link to download the source ASAP.
Joe
Ok. I will do some code-cleaning and code-commenting and put a source link here. Please give me a day.
Thanks for this project... it was really useful, and i have a question about this... actually I made server and client... they work OK, but I'd like to send not just message ... i 'd like to enable file transfer over sockets... what means that i have to make a difference between client_messages and file_transfering... so I do it and i know when i am receiving message, when file... now i want in my textbox put an icon or something like it... like on msn when you are receiving file and option to choose "Accept" or "Don't accept" ... is it possible ... to put picture in textBox ... and to put a text like "Accept" and set event on it... what is the difference between richTextBox, Windows.forms.textBox and Windows.Controls.textBox... Thanks!!
http://www.daniweb.com/forums/thread25861.html
heh I've found it ;)if somebidy one has the same problem... resolution is here
Hey Twister. Any idea on when you can get that chat server and client completed. I wanted it real bad.
Hey Twister. Any idea on when you can get that chat server and client completed. I wanted it real bad.
Hey Joe (and others),
Sorry for the delay. Work and stuff kept me from making my own deadline.
Anyway, it can be downloaded from http://www.rene-jansen.nl/?p=230
The site is in Dutch, but you need the download link "hier" to download the entire Chat system. Hope it works for all you guys/girls
Twister
remove from list
Great TuT,
can anyone send me complete working code with implemented sending private message at ap14683@etf.unsa.ba
it is urgent
Thanks
Amir
Great TuT,
can anyone send me complete working code with implemented sending private message at ap14683@etf.unsa.ba
it is urgent
Thanks
Amir
Hi! Amir, just download it from this link
http://www.rene-jansen.nl/?p=230
Thank you a lot
@Joe, does it function the way you like? I would like some comment (good or bad)
René
Twister. This is a lot better. It works great. You did a nice job. Thanks. I been wanting one for a long time. and I never could under stand how to do servers and crap like that.
learning!~
learning!~
Hi! Looks like the other thread is dead now? so i'm reposting here.
I'm having a trouble with old code.
When i'm disconnecting a client with button i get an IOException 10004:
Unable to read data from a transport connection
A blocking operation was interrupted by a call to WSACancelBlockingCall
in a while cicle in ReceiveMessages() function
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
It looks like it still trying to get message when Sender, Receiver and Server are already closed. Maybe it's because it was already in the while when Connected become false and those were closed.
It happens even when i'm closing a client.Oh, and i'm using a VisualStudio2008
Hi! Try downloading the newer one. You will find it as I posted it. With the link. Just down load that one. It works a lot better.
Just want to add that code is correct but if you use a newer version of Visual Studio other than 2005 best download code and convert it, this will do the trick to make it work
Sorry No it won't. You will need to upgrade to VS 2008 express or VS 2010.
yes that what I meant when I said newer version(vs 2005 = old, 2008 or 2010 = newer or higher) sorry for not specifying before, but anyways great tutorial
Whatever you do, do not post a messaage on this board. You will get every response sent to your e-mail until the end of time. This should give you an idea of how useful and thorough the chat code is as this board shows the same level of design consideration and lifecycle. For GODS SAKE, GIVE ME AN OPT-OUT ABILITY!!!
Also, Fix you code so that it gracefully exits...what a turd!
Yes I know. I fount out way too late. They need an option so that we can take us off the list.
As of fixing the the code. That's what all of us have been trying to do. That's why twister rewrote it. It better then the one in this tutorial.
@igor
If you really need the old code I can give you the reason and solution.
Reason:
srReceiver.Readline() is a blocking method. It waits for any new data before the invoke is actually called.
When you disconnect the client it still waits for new data and thats why you get the exception.
Solution
You can catch the exception and close the reader and writer gracefully. Something like below (do not copy/paste! I wrote this from my head)
while (Connected)
{
try
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch(SocketException ex)
{
srReceiver.Close()
srSender.Close()
GB.Collet() //Collect garbage
}
}
Thank you Twister.
I've add a private messaging in old code. Like "/w Somebody text". And showed that to teacher.
It was an exam today and I've passed it with A.
Great tutorial but maybe it's time for a new one?
Oh, we have a cheater in our room. Shame on you.
No thanks. I'm just happy that it worked for you.
I think I will make a tutorial of my code. But I will post it on my website as well as here. Because lets be honest, thats where my website is for.
And this time I will not set a deadline for the tutorial. Making a tutorial is quite more time consuming in comparison with programming (for any IT person).
great! I also make some tutorials in my web page I have to admit that this is well explained and time dedicated not like others where you finally get confused. I appreciate your work.
Thank you.
great! I also make some tutorials in my web page I have to admit that this is well explained and time dedicated not like others where you finally get confused. I appreciate your work.
Thank you.
I can connect through a local network no problem between various computers, but I can't get this to work for it to listen using my wanip for users on outside networks to connect. Any ideas?
Alex. Make sure your firewall has that open in it's list. and that you don't have some thing blocking it. It works. I have all ready try it. It's real good too.
Hi Can some please send me or share there custom code to get this chat application to work.
Thanks in advance
Hi Can some please send me or share there custom code to get this chat application to work.
Thanks in advance
@Alex. My version of the chat application uses port 50000. So if you open/forward that port on your modem/router/firewall it will work. I have tested this myself.
@Pat. Download is available at http://www.rene-jansen.nl/?p=230
But know that I rewrote the whole thing and some credits should go to Andrei
Update on tutorial. I'm almost done with the tutorial on the client and the server. So please be patient. It will take me a week or 2 to polish the whole thing.
Sincerely,
Rene
Uhmmm. . . to solve the problem of some threads still running after form close. You can Add an OnAplicationClose event , and in the method specify.
Environment.Exit(Environment.ExitCode);
to keep the client from crashing on disconnect you should modify your code in the following places:
Under the private void RecieveMessages() method replace the bottom of the method with the following code starting from the same comment listed here in the beginning.
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
try
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch (IOException iEx)
{
MessageBox.Show(iEx.Message);
}
}
This will keep it from crashing on you. You can customize the exception as you wish. Enjoy.
to keep the client from crashing on disconnect you should modify your code in the following places:
Under the private void RecieveMessages() method replace the bottom of the method with the following code starting from the same comment listed here in the beginning.
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
try
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch (IOException iEx)
{
MessageBox.Show(iEx.Message);
}
}
This will keep it from crashing on you. You can customize the exception as you wish. Enjoy.
to keep the client from crashing on disconnect you should modify your code in the following places:
Under the private void RecieveMessages() method replace the bottom of the method with the following code starting from the same comment listed here in the beginning.
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
try
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch (IOException iEx)
{
MessageBox.Show(iEx.Message);
}
}
This will keep it from crashing on you. You can customize the exception as you wish. Enjoy.
hi, Felow Coders
I just downloaded the source code and try it on the Visual Studio 2005, but i found a problem on the closing procedure, the server however always repeating the users leaving message like Administrators: Sywa has left us, over and over again..
I trace through the server code and found the problem in RemoveUser, here is the walkthrough of the problem.
public static void RemoveUser(TcpClient tcpUser)
{
try
{
// If the user is there
if (htConnections.Count > 0) //--> i modified this part
{
string users = TCPServer.htConnections[tcpUser].ToString();
// Remove The user first Rather than Sending the message first
// Remove the user from the hash table
TCPServer.htUsers.Remove(TCPServer.htConnections[tcpUser]);
TCPServer.htConnections.Remove(tcpUser);
// First show the information and tell the other users about the disconnection
//Before the Modification This part always
//looping and back again from to start so the
//TCPServer.htUsers.Remove(TCPServer.htConnections
//[tcpUser]);
//And
//TCPServer.htConnections.Remove(tcpUser);
// Was never hit
SendAdminMessage(users " has left us");
}
}
catch (InvalidOperationException ivox)
{
Console.WriteLine("Exception occured : " ivox.Message);
}
} // end RemoveUser
Very good.
Related Tutorials
Related Source Code
C# Job Search