Ext.: http://www.cnblogs.com/mobwiz/p/3715743.html
Recently need to add desktop sharing in the product features, temporarily do not realize remote control; Reference to some of the garden articles, added some of their own changes.
Requirements : Display the desktop of a machine over a network to multiple client screens, displaying content that may be ppt,word documents, without video.
1) Capture Screen
Refer to the section of code found online below
StaticBitmapSource Copyscreen () {using (var screenbmp = new Bitmap (( int) Systemparameters.primaryscreenwidth, (int) Systemparameters.primaryscreenheight, System.Drawing.Imaging.PixelFormat.Format32bppArgb) {using (var bmpgraphics = Graphics.fromimage (screenbmp ) {Bmpgraphics.copyfromscreen (0, 0, 0, 0return Imaging.createbitmapsourcefromhbitmap ( Screenbmp.gethbitmap (), IntPtr.Zero, Int32rect.empty, Bitmapsizeoptions.fromemptyoptions ()); } }}
Looks very concise, but after running, found unexpectedly have memory leaks, memory continues to rise, from the 30MB has risen to more than 1G, do not stop, so modified as follows, to eliminate the memory leak:
Calling the DeleteObject in the API
[System.Runtime.InteropServices.DllImport ("gdi32.dll")] bool DeleteObject (INTPTR hobject );
PrivateBitmapSource Copyscreen () {var handle =IntPtr.Zero; BitmapSource Source =Null;Try{var bitmap =New Bitmap ((intintvar g = Graphics.fromimage (bitmap); G.copyfromscreen ( Span style= "color: #800080;" >0, 0, 0, 0, bitmap. Size); Handle = bitmap. Gethbitmap (); SOURCE = Imaging.createbitmapsourcefromhbitmap (handle, IntPtr.Zero, Int32rect.empty, Bitmapsizeoptions.fromemptyoptions ()); } finally {DeleteObject (handle);} return source;}
After this processing, the capture screen no longer causes a memory leak, the memory consumption is not growing steadily;
2) Transmission
Because the shared client may be one-to-many, it can no longer use TCP point-to-point transmission, try to use UDP multicast mode to transfer data, encountered a lot of problems;
The UDP multicast method is no longer mentioned, the advantage of using multicast is that the server network bandwidth consumption will not increase due to the increase of the client.
Problem one : The UDP message has a maximum length limit , so it is not possible to send one picture at a time
solution : Self-splitting transmission, reorganization at the receiving end, defining the message Class
Class packet{ int SN {get; Setbyte[] Data {get; Setbyte[] Tobytes () {...}}
The segmentation message and the reorganization message are no longer detailed. After the message is sent, an end flag is sent, the receiving side reorganizes the message, and the image is displayed. The local test OK, and then put on the client, the problem came out.
issue two : UDP itself is unreliable , so the order in which messages arrive may be chaotic and messages will be lost
solution : Each picture, give a GUID, and add a timestamp; the receiver uses a buffer -capable receive mode; works as follows:
1) Sender: Each time interval to grab a picture, generate a GUID, and then the message segmentation, and then send the message to the multicast address, each message contains a GUID, the number of messages, message serial number, time stamp and data;
2) Receiving end:
A) after receiving a message, put into the message pool;
b) Discard the time-out message (check timestamp, message discard over a certain time, for example, 5 seconds, this application does not require strict data integrity, not received, discarded)
c) Check all the messages in the buffer, check the message of the earliest time, and check its integrity (if the message should have three, whether has received three simultaneously have the GUID of the message), if the GUID of the message is complete, then trigger the picture prepared event (ImageReady), and delete all the message data of the picture;
D) The client displays the image through the ImageReady event;
test result : Native test OK, LAN test failed again, view debug information Discovery client always can only receive all the first @......*#......@ in the message, the others are lost ~
three : UDP packet loss on LAN? @#
Solution: When sending a paper, add a certain interval. This is to try out, the reason may be too fast, the network can not transmit, lost;
The final code structure is as follows:
Message class:
Classpacket{PublicDouble Time {GetSet;}Publicint Total {get; setpublic int SN {get;< Span style= "color: #0000ff;" >setpublic byte["Data {get ; setpublic Packet () {...} public byte["Tobytes ( ) {....} public static Packet frombytes ( byte[] bytes) {...}}
Publicshareserver{PublicShareserver () {}
//Pseudo-code, non-operational codePublicvoidStart () {1) Initialize the UdpClient for multicast//2) Open a thread and enter the loopWhile(_doing) {var Source =Copyscreen ();if (Source = =NullContinue;var guid =Guid.NewGuid ();//JPEG encodingvar enc =New Jpegbitmapencoder () {qualitylevel =40};var ms =NewMemoryStream (); Enc. Frames.add (bitmapframe.create (source)); Enc. Save (MS);//Compression MemoryStream//GZipStreamvar data =Compress (Ms. ToArray ());// split message var packages =< Span style= "color: #000000;" > Splitpackagets (data, GUID); // transmit message foreach (var packaget packages) { var bytesarray = Packaget. Tobytes (); _udpclient.send (Packaget. Tobytes (), bytesarray.length); // add an interval Thread.Sleep ( 100// 1 seconds to grab the diagram Thread.Sleep ( 1000
Receiving end:
Classbufferedscreenclient{PublicEvent eventhandler<imagereadyeventargs>ImageReady;Private list<packet>_packets;PublicBufferedscreenclient () {...}PublicvoidAddpacket (Packet Packet) {1) add message 2) Clear 3) Check if the oldest picture is OK, if OK triggers ImageReady event a) First query out this group of messages B) Merge This set of messages, get data C) extract D) JPEG decode into BitmapSource e) Remove the image of the message data F) Through the event, the picture is sent to the receiving end for display _packagets. ADD (packet); Cleanpackets (); var source = Getfirstimage (); if (Source! = null
private void cleanpackets () {...}
private void mergepackets (ienuerable<packet > Packets) {...}
Private BitmapSource Getfirstimage () {...}
}
After testing, a server + two clients can receive the picture, but the first figure out of the relatively slow, the network sent this piece, also need to be optimized. Picture quality and send interval, can be adjusted according to the network condition;
TODO List
1) Optimize message sending and message receiving mechanism
2) Picture chunked send
3) Compare the difference between two times, the film does not change and does not send
4) Optimize the mechanism of the receiving end
Reference:
1) Twilight Rain ice blue C # LAN share series article http://www.cnblogs.com/liuxiaobo93/p/3675387.html
2) C # multicast
3) WPF Under-screen capture, etc.
C # using UDP multicast for LAN desktop Sharing