Node.js– A chat server written in Node and a client app written in C#

A new twist to a boring Chat application

Most demos on Node.js illustrate how to create a chat server, but rarely provide the client side of the chat service.

That is what this post is about – creating both the server and client side of the equation.

Server Node.js Javascript
Client .NET C#

Node.js – Chat Application – Server Side

This is your traditional Node.js chat application. I’ve commented it pretty heavily. Note the following:

Create a TCP socket listener var s = net.Server(function(socket)....
Saving the socket connection so we can send message back to the client sockets.push(socket)....
An event that represents a client sending a text msg to server. 'data' represents the event and msg_sent is the data sent by chat client application. socket.on('data', function(msg_sent) {....
Don't echo back the message to the sender if(sockets[i] == socket) continue;
Write message back to listeners (except original sender) sockets[i].write(msg_sent);
An event when a client disconnects. We need to remove dead sockets from our array. socket.on('end', function() {
Listening on http://localhost:8000 s.listen(8000);

Filename = lamechat.js

 net = require('net')// Supports multiple client chat application// Keep a pool of sockets ready for everyone// Avoid dead sockets by responding to the 'end' eventvar sockets = [];// Create a TCP socket listenervar s = net.Server(function (socket) {    // Add the new client socket connection to the array of    // sockets    sockets.push(socket);    // 'data' is an event that means that a message was just sent by the     // client application    socket.on('data', function (msg_sent) {        // Loop through all of our sockets and send the data        for (var i = 0; i < sockets.length; i++) {            // Don't send the data back to the original sender            if (sockets[i] == socket) // don't send the message to yourself                continue;            // Write the msg sent by chat client            sockets[i].write(msg_sent);        }    });    // Use splice to get rid of the socket that is ending.    // The 'end' event means tcp client has disconnected.    socket.on('end', function () {        var i = sockets.indexOf(socket);        sockets.splice(i, 1);    });});s.listen(8000);console.log('System waiting at http://localhost:8000');        

Creating Chat Applications in .NET and C#

This next section will demonstrate the building of a chat client for the Node.js server.

Create a new Visual Studio Project

0rwqfvaw

Project type = Windows Presentation Foundation Application

1trjcspd

Editing MainWindow.xaml

Right mouse click on MainWindow.xaml

amvh2cko

Where to add the various controls

We are adding textboxes, command buttons.

xdctzss1

The graphical interface – MainWindow.xaml

MainWindow.xaml is where we define our user interface. We have 3 text boxes and 2 buttons.

txtChatName Allows you to login with an id
txtConversation Where the conversation between chat clients can be seen
txtOutMsg The text message a given chat client wants to send to others
cmdConnect Allows you to login and connect using txtChatName
cmdSendMessage Sends your text message that was typed into txtOutMsg

Filename = MainWindow.xaml

 <Window  x:Class="NodeJsChatClient.MainWindow"  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  Title="Chat Client"  Height="350"  Width="525">    <Grid>
        <Button      Content="Connect"      Height="29"      HorizontalAlignment="Left"      Margin="12,12,0,0"      Name="cmdConnect"      VerticalAlignment="Top"      Width="144"      Click="cmdConnect_Click"/>        
       <TextBox      AcceptsReturn="True"      Margin="14,51,12,93"      Name="txtConversation"      Text=""      TextWrapping="Wrap"      VerticalScrollBarVisibility="Visible"/>        
       <TextBox      Height="33"      HorizontalAlignment="Left"      Margin="182,12,0,0"      Name="txtChatName"      VerticalAlignment="Top"      Width="148"      Text="Bruno"/>
               <TextBox      Height="36"      HorizontalAlignment="Left"      Margin="14,229,0,0"      Name="txtOutMsg"      VerticalAlignment="Top"      Width="477"/>
               <Button      Content="Send Message"      Height="28"      HorizontalAlignment="Left"      Margin="12,271,0,0"      Name="cmdSendMessage"      VerticalAlignment="Top"      Width="479"      Click="cmdSendMessage_Click"/>        
     </Grid></Window>

What the finished interface looks like

All the controls have been added.

sbuqjcby

The code behind – C# – chat client application logic

The next section is about writing the client code that connects, sends, and receives text/chat messages.

Proper Using Statements

“using” statements are needed to minimize typing in large amounts of code.

 using System.Net.Sockets;using System.Threading.Tasks;using System.Threading;using System.Windows.Threading;        

The final code in MainWindow.xaml.cs

This represents all the code needed to complete the C#-based client application.

Adding the code behind.

2dyyaddx

MainWindow.xaml.cs

Here is the entire code-behind module. No extra references are needed.

 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;using System.Net.Sockets;using System.Threading.Tasks;using System.Threading;using System.Windows.Threading;namespace NodeJsChatClient{    public partial class MainWindow : Window    {        // Declare member objects        // Client for tcp, network stream to read bytes in socket        TcpClient tcpClient = new TcpClient();        NetworkStream serverStream = default(NetworkStream);        string readData = string.Empty;        string msg = "Conected to Chat Server ...";        public MainWindow()        {            InitializeComponent();        }        // Purpose:     Connect to node.js application (lamechat.js)        // End Result:  node.js app now has a socket open that can send        //              messages back to this tcp client application        private void cmdConnect_Click(object sender, RoutedEventArgs e)        {            AddPrompt();            tcpClient.Connect("127.0.0.1", 8000);            serverStream = tcpClient.GetStream();            byte[] outStream = Encoding.ASCII.GetBytes(txtChatName.Text.Trim()                                  + " is joining");            serverStream.Write(outStream, 0, outStream.Length);            serverStream.Flush();            // upload as javascript blob            Task taskOpenEndpoint = Task.Factory.StartNew(() =>            {                while (true)                {                    // Read bytes                    serverStream = tcpClient.GetStream();                    byte[] message = new byte[4096];                    int bytesRead;                    bytesRead = 0;                    try                    {                        // Read up to 4096 bytes                        bytesRead = serverStream.Read(message, 0, 4096);                    }                    catch                    {                        /*a socket error has occured*/                    }                    //We have rad the message.                    ASCIIEncoding encoder = new ASCIIEncoding();                    // Update main window                    AddMessage(encoder.GetString(message, 0, bytesRead));                    Thread.Sleep(500);                }            });        }        // Purpose:     Updates the window with the newest message received        // End Result:  Will display the message received to this tcp based client        private void AddMessage(string msg)        {            Dispatcher.BeginInvoke(DispatcherPriority.Input, (ThreadStart)(             () =>             {                 this.txtConversation.Text += string.Format(                          Environment.NewLine + Environment.NewLine +                          " >> {0}", msg);             }));        }        // Purpose:     Adds the " >> " prompt in the text box        // End Result:  Shows prompt to user        private void AddPrompt()        {            txtConversation.Text = txtConversation.Text +                 Environment.NewLine + " >> " + msg;        }        // Purpose:     Send the text in typed by the user (stored in        //              txtOutMsg)        // End Result:  Sends text message to node.js (lamechat.js)        private void cmdSendMessage_Click(object sender, RoutedEventArgs e)        {            byte[] outStream = Encoding.ASCII.GetBytes(txtOutMsg.Text);            serverStream.Write(outStream, 0, outStream.Length);            serverStream.Flush();        }    }}       

Let’s build the project

Right mouse click to see the “rebuild” command.

pd2bwa3k

Should be a clean “recompile”

“0” errors.

image

 

Testing NodeJsChat

It is time to test the applications.

Start by running lamechat.js

Done at a command prompt.

image

Run the executables

Start by opening the project folder and navigating to the “bin\debug” folder.

image

We need at least two client chat applications to test

You will simply run NodeJsChatClient.exe twice.

image

The final test

Login to both and then start sending messages.

image

This represents the final step

Now just improve what I did and send it back to me Smile

image 


Download for Azure SDK