Background Information:
Since PowerShell is built on top of the .NET framework, it is possible for us to reuse all of its classes and objects. Now, those of you who know me, know I’m a developer at heart. I’ve always been a developer, and probably always will be. When I first started learning the .NET platform back in 2003, one of the first project I did on my own was to create a chat application using a C# console app. Not sure if you remember, but chats used to be the big thing before Facebook and text messages took over 🙂 Anyway, I decided to give myself a challenge and see if I could recreate such a chat module using strictly PowerShell scripts.
How does it work?:
In every “server-client chat engine you need at least two main components: a server instance, that will act as a dispatcher for messages received, and a client instance that will connect to the chat server and will post messages. For the purpose of this excercise will will be using the TCPListener .NET object to represent the server instance, and the TCPClient .NET object for the client one.
Server Instance:
To instantiate the server instance, we need to declare a new TCPListener object on the server, and specify a port on which it will be listening for incoming connections. In our case, our TCPListener will be listening on port 777. To tell the TCPListener object to start listening and accepting incoming connection, we need to call its Start() method. This method will put our PowerShell script in an idle state until a connection is received. For the sake of keeping things simple, our demo will only accept a single connection, meaning only one client will be allow to connect to our server at any given time. Once a connection has been established with a client, the server instance will obtain a reference to the communication channel (stream) with the client and will await for incoming messages. Because we want to server to be continuouosly listening for incoming messages, we will be using an infinite loop while($true). Everytime a message is received from the client, the message will be printed on screen using yellow text. The following PowerShell code will be used for generating the server instance:
function Listen()
{
$endpoint = new-object System.Net.IPEndPoint([system.net.ipaddress]::any, 777)
$listener = new-object System.Net.Sockets.TcpListener $endpoint
$listener.Start()
$client = $listener.AcceptTcpClient()
Write-Host “Client”$client.Client.RemoteEndPoint.Address”connected” -BackgroundColor Green
[System.IO.StreamReader]$stream = new-object System.IO.StreamReader -argumentList $client.GetStream()
while($true)
{
$line = $stream.ReadLine()
if($line -ne $null)
{
Write-Host $line -ForegroundColor Yellow
}
}
$listener.Stop()
}
Listen
Client Instance:
The client instance will simply take care of connecting to the remote server (in our case we connect to the localhost because everything runs on the same box), and once the connection has been established, will send and “Hello There!” message to the remote server instance. To connect remotely, we will call the Connect() method on the TCPClient object, passing it the IP address of the server, and the port on which we wish to establish the connection (it needs to be the same port the server is listening on). The following PowerShell code will be used to generate the Client instance:
function Connect()
{
$client = New-Object System.Net.Sockets.TcpClient
$client.Connect(“localhost”,777)
$stream = new-object System.IO.StreamWriter $client.GetStream()
$stream.WriteLine(“Hello there!”)
$stream.Flush();
$client.Close()
}
Connect
Putting it Together:
For this demo, we will be running both the client and server instance on the same local machine, however, to differentiate each instance, we will configure the server session to have a Teal background with white text, and the client instance to have a pink background with black text.
Server:
Client:
Then, we need to initiate the server instance, and have it wait for incoming connections:
Next, we initiate the Client instance, which will connect to the remote server and automatically send a message:
Enjoy!