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

 

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

  • Comments 4
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' event
var sockets = [];

// Create a TCP socket listener
var 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


  • Hi Bruno,

    your tutorial is amazing :)

    I have one question about the client side: what is the purpose of that Thread.Sleep(500) at the end of taskOpenEndpoint?

    Thank you in advance.

  • Hello Erik,

    As you can notice, that piece of code is wrapped in an infinite loop "while(true)".

    The idea of that Thread.Sleep is to make sure that the CPU doesn't hit high utilization levels due to just fetching between instructions.

    Cheers,

  • Hello BrunoTerkaly,

    your tutorial is helpful, I really like it.

    I am a newbie in node.js.

    your tutorial can chat between 2 .net app but I try make a application to chat between web and .net app, but I don't know how to do website part.

    could you please help me

  • Hello BrunoTerkaly,

    I mean that I want to make Chat Applications in Html and javascript instead of in .NET and still using node.js server

Page 1 of 1 (4 items)
Leave a Comment
  • Please add 3 and 2 and type the answer here:
  • Post