Hi, I'll show you how to write a Remote - Desktop client using C # + XNA

This
topic inspired me to write this article.
A bit of myself
I waited a long time for the second part of that article, but I did not wait. As the author argued, the second article was supposed to be the implementation of image transmission via UDP protocol to a remote client. After that I tried to implement the second part of the article myself, but it always turned out badly. Due to the slow drawing of the GDI, the program simply hung on the computer
Core 2 Duo 2.66 GHz, Nvidia GeForce 9600 GT . I used different optimization algorithms, but it didn't help much and then I decided to use XNA.
Selection of transmission protocol
I wanted very much to choose the TCP transfer protocol, there are fewer problems with it, but I chose UDP, because everyone says that it is better for such cases to take blah blah blah ... You’re probably wondering why there are more problems with UDP? The answer is simple - a UDP message cannot exceed 65,507 bytes in size, which is not very convenient. Our packets average 130,000 bytes in size (for a screen size of 1366x768), when we try to send such a packet, an error occurs, as shown below.

')
This problem can be solved in two ways:
1) Create a crutch
2) Create a structure
1) Since I'm lazy, I chose a crutch. The crutch is to break a larger message into many small ones and write the number of pieces in the first message that will be sent. I called it a crutch, because, having lost the first message, the program
will fly to hell to not properly glue the image (it will not know how many parts the image is broken into).
2) You can break the screen into many pieces and remember their coordinates. All this will need to be stored in the structure, which is very convenient, by the way, this algorithm will help to make optimization in the future.
Practice
I'll start with a simple one. From the sender. We will send screenshots of our screen to a remote computer. I wrote a function for loading data and initializing some variables.
The launch point is our Run () function.
public void Run() { Load();
Load () data is loaded first, variables are declared and looped. In the loop, we get the screen image, convert it to a byte array, use my crutch (splitting the message into several messages - CutMsg (bytes)), send all the packets.
Nothing interesting happens in the Load () function.
Two lines will be read from the
ip.txt file. The first line is the IP address to which you want to send data. The second line is the Port to which the sending will occur. Also there will be getting the length and width of the screen.
Conversion function
private byte [] ConvertToByte(Bitmap bmp) { MemoryStream memoryStream = new MemoryStream();
And the most interesting is the implementation of the crutch.
private List<byte[]> CutMsg(byte[] bt) { int Lenght = bt.Length; byte[] temp; List<byte[]> msg = new List<byte[]>(); MemoryStream memoryStream = new MemoryStream();
I share the data on blocks of 65,500 (the number took less to clearly get) and write them to the sheet of byte arrays, after I return this sheet.
Recipient Code
It’s more complicated with the recipient, I used delegates and events there for asynchronous work and I don’t want to bore you with code that I’ll write the main thing.
Asynchronous data retrieval.
int countErorr = 0; private void AsyncReceiver() { IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0); while (true) { try { MemoryStream memoryStream = new MemoryStream(); byte[] bytes = udpClient.Receive(ref ep); memoryStream.Write(bytes, 2, bytes.Length - 2); int countMsg = bytes[0] - 1; if (countMsg > 10) throw new Exception(" "); for (int i = 0; i < countMsg; i++) { byte[] bt = udpClient.Receive(ref ep); memoryStream.Write(bt, 0, bt.Length); } GetData(memoryStream.ToArray()); memoryStream.Close(); } catch { countErorr++; } } }
We again see the looping, then we get the first packet, we read the first byte from it (the number of future messages is written in this byte), if the message is longer than 10, we obviously lost the first packet, therefore we add the loss counter, otherwise we get all the messages - we glue them into one and raise the GetData event (byte []).
In GetData (byte []) we get Texture2D, converting it from an array of bytes.
private void Receive_GetData(byte[] Date) { BackGround = ConvertToTexture2D(Date); } private Texture2D ConvertToTexture2D(byte[] bytes) { MemoryStream memoryStream = new MemoryStream(bytes); System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(memoryStream);
You can download the whole project at the end of the article, so do not despair if I have not written something.
Results and conclusion
As a result, when the “sender” and “receiver” are simultaneously launched, recursion and a huge amount of losses occur on their computer (30–90 losses), when the “sender” is started on my computer, and on the computer of the “receiver” parents, there is at least a loss (10 15 losses). Both computers (parents and mine) are connected to the same Wi-Fi network with a 54 Mbit / s channel. There is a ping (about 250 ms.) - reminds by ping TeamViewer. If you add optimization and replace the crutch, you get a great program for image transfer.
Recursion

Parents computer (image transfer from my computer to theirs)

What does a loss look like?

In the next article I will finish the program, or rather add the ability to remote control and maybe even optimize it.
Download
projectDownload
Receiver (Receives Images)
Download
Sender (Sends Images)
PS I reloaded the source code on github
github.com/Luchanso/remote-desktop