Xamarin.Forms - Controlling Your PC 🖥️ With Your Phones📱Using TCP/IP Protocol - Part Two

Introduction

 
Last time, we performed the workstation's sleep functionality on the basis of the client app SLP2 command. In this second and final part of my article series, we will complete the functionality of both of our applications, client and server. First, we will talk about how the screenshot functionality will perform because the client will only send the TSC1 command and the server will receive this. Then, on the basis of this command, the TakeScreenshot function that we will write inside the server app will perform.
 
After capturing the screenshot of the current activity of the workstation, we will send it to the client. The size of the picture could be large and we cannot send the large data to the client. Therefore, to achieve this target, we will convert the screenshot data into byte-type packets and then send it to the client. When the client will receive the byte-type packets, it will have to convert into its original form. We will also perform the shutdown functionality. If a client sends SHTD3 command to the server application, the server will execute the shutdown function.

Server Application

 
Let's go back to the server application and write the functionality of screenshot and shutdown workstation. Open the program.cs file and write the following code inside the while loop, that we had implemented in the last episode. In the while loop, we put the try-catch block and inside, we wrote the condition of If-Else. After if sleep check, you will write the following code.
  1. else if (data.ToUpper().Contains("SHTD3")) {  
  2.     Console.WriteLine("Pc is going to Shutdown!" + " \n");  
  3.     Shutdown();  
  4. else if (data.ToUpper().Contains("TSC1")) {  
  5.     Console.WriteLine("Take Screenshot!" + " \n");  
  6.     var bitmap = SaveScreenshot();  
  7.     var stream = new MemoryStream();  
  8.     bitmap.Save(stream, ImageFormat.Bmp);  
  9.     sendData(stream.ToArray(), client.GetStream());  
  10. }  

Shutdown and TakeScreenshot Functions

 
Add the following namespaces to the server application. Otherwise, Visual Studio will not recognize the graphics keyword of the screenshot function.
  1. using System.Drawing;  
  2. using System.Drawing.Imaging;   
Go back to program.cs and put these functions inside the main class.
  1. //Workstation Shutdown function  
  2. void Shutdown() {  
  3.     System.Diagnostics.Process.Start("Shutdown""-s -t 10");  
  4. }  
  5. //Save Screenshot function  
  6. Bitmap SaveScreenshot() {  
  7.     var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);  
  8.     // Create a graphics object from the bitmap.  
  9.     var gfxScreenshot = Graphics.FromImage(bmpScreenshot);  
  10.     // Take the screenshot from the upper left corner to the right  
  11.     bottom corner.  
  12.     gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);  
  13.     return bmpScreenshot;  
  14. }  
  15. //Convert Image to byte type data.  
  16. void sendData(byte[] data, NetworkStream stream) {  
  17.     int bufferSize = 1024;  
  18.     byte[] dataLength = BitConverter.GetBytes(data.Length);  
  19.     stream.Write(dataLength, 0, 4);  
  20.     int bytesSent = 0;  
  21.     int bytesLeft = data.Length;  
  22.     while (bytesLeft > 0) {  
  23.         int curDataSize = Math.Min(bufferSize, bytesLeft);  
  24.         stream.Write(data, bytesSent, curDataSize);  
  25.         bytesSent += curDataSize;  
  26.         bytesLeft -= curDataSize;  
  27.     }  
  28. }  
We have finished our server application and all its functionality. Let's start to code our client application.
 

Client Application

 
Step 5 - Create Operations Page
 
Go back to the client application (Xamarin.Forms) and add new ContentPage with name OperationsPage. Inside this layout, add the following code to create more buttons and picture holders.
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
  4.              xmlns:local="clr-namespace:XamarinForms.Client"  
  5.              x:Class="XamarinForms.Client.OperationsPage">  
  6.     <ContentPage.Content>  
  7.         <StackLayout Orientation="Vertical">  
  8.             <Button x:Name="Screenshot" Text="Screenshot" Clicked="Screenshot_Clicked"/>  
  9.             <Button x:Name="Sleep" Text="Sleep" Clicked="Sleep_Clicked"/>  
  10.             <Button x:Name="Shutdown" Text="Shutdown" Clicked="Shutdown_Clicked"/>  
  11.             <Image x:Name="imageView"/>  
  12.   
  13.         </StackLayout>  
  14.     </ContentPage.Content>  
  15. </ContentPage>  
Step 6 - Add Pending Methods in Operation Class
 
Open the OperationPage.xaml file and replace the following code with the appropriate namespaces.
  1. using System;  
  2. using System.IO;  
  3. using System.Net.Sockets;  
  4. using System.Text;  
  5. using Xamarin.Forms;  
  6. using Xamarin.Forms.Xaml;  
  7.   
  8. namespace XamarinForms.Client  
  9. {  
  10.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  11.     public partial class OperationsPage : ContentPage  
  12.     {  
  13.         public OperationsPage ()  
  14.         {  
  15.             InitializeComponent ();  
  16.         }  
  17.         
  18.         //Sleep Button Command  
  19.         private void Sleep_Clicked(object sender, EventArgs e)  
  20.         {  
  21.             var client = Connection.Instance.client;  
  22.             NetworkStream stream = client.GetStream();  
  23.             String s = "SLP2";  
  24.             byte[] message = Encoding.ASCII.GetBytes(s);  
  25.             stream.Write(message, 0, message.Length);  
  26.         }  

  27.         //Shutdown Button Command  
  28.         private void Shutdown_Clicked(object sender, EventArgs e)  
  29.         {  
  30.             var client = Connection.Instance.client;  
  31.             NetworkStream stream = client.GetStream();  
  32.             String s = "SHTD3";  
  33.             byte[] message = Encoding.ASCII.GetBytes(s);  
  34.             stream.Write(message, 0, message.Length);  
  35.         }  

  36.         //Screenshot Button Command  
  37.         private void Screenshot_Clicked(object sender, EventArgs e)  
  38.         {  
  39.             var client = Connection.Instance.client;  
  40.             NetworkStream stream = client.GetStream();  
  41.             String s = "TSC1";  
  42.             byte[] message = Encoding.ASCII.GetBytes(s);  
  43.             stream.Write(message, 0, message.Length);  
  44.             var data = getData(client);  
  45.             imageView.Source = ImageSource.FromStream(() => new MemoryStream(data));  
  46.         }  
  47.   
  48.         //Data Collecting from Server  
  49.         public byte[] getData(TcpClient client)  
  50.         {  
  51.             NetworkStream stream = client.GetStream();  
  52.             byte[] fileSizeBytes = new byte[4];  
  53.             int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);  
  54.             int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);  
  55.   
  56.             int bytesLeft = dataLength;  
  57.             byte[] data = new byte[dataLength];  
  58.   
  59.             int buffersize = 1024;  
  60.             int bytesRead = 0;  
  61.   
  62.             while (bytesLeft > 0)  
  63.             {  
  64.                 int curDataSize = Math.Min(buffersize, bytesLeft);  
  65.                 if (client.Available < curDataSize)  
  66.                     curDataSize = client.Available;//This save me  
  67.   
  68.                 bytes = stream.Read(data, bytesRead, curDataSize);  
  69.                 bytesRead += curDataSize;  
  70.                 bytesLeft -= curDataSize;  
  71.             }  
  72.             return data;  
  73.         }  
  74.     }  
  75. }  

Testing Operations

 
Workstation Sleep Operation
 
Run both projects - server and client. Put the workstation IP address and port that you can see on the server application output screen into the client application and hit "Connect". After connecting with the server, now you can perform your task. Now press the Sleep button. Your workstation will go to into sleep mode.
 
Xamarin.Android – Build Real Life Application-using TCP/IP
 
Workstation Take Screenshot Operation
 
Click on the "Take Screenshot" button; after a few seconds, you will see the screenshot of the workstation inside the client application.
 
Xamarin.Android - Build Real Life Application Using TCP/IP - Part Three
 
Workstation Shutdown Operation
 
After logging in and building the connection with the server, hit the "Shutdown" button. You will see a notification that your PC will be shut down in 30 seconds.