Efficient way to send images via WCF?

后端 未结 7 1845
野的像风
野的像风 2020-12-02 09:48

I am learning WCF, LINQ and a few other technologies by writing, from scratch, a custom remote control application like VNC. I am creating it with three main goals in mind:

相关标签:
7条回答
  • 2020-12-02 09:53

    The fastest way to send data between client/server is to send a byte array, or several byte arrays. That way WCF don't have to do any custom serialization on your data.

    That said. You should use the new WPF/.Net 3.5 library to compress your images instead of the ones from System.Drawing. The functions in the System.Windows.Media.Imaging namespace are faster than the old ones, and can still be used in winforms.

    In order to know if compression is the way to go you will have to benchmark your scenario to know how the compression/decompression time compares to transferring all the bytes uncompressed.

    If you transfer the data over internet, then compression will help for sure. Between components on the same machine or on a LAN, the benefit might not be so obvious.

    You could also try compressing the image, then chunk the data and send asynchronously with a chunk id which you puzzle together on the client. Tcp connections start slow and increase in bandwidth over time, so starting two or four at the same time should cut the total transfer time (all depending on how much data you are sending). Chunking the compressed images bytes is also easier logic wise compared to doing tiles in the actual images.

    Summed up: System.Windows.Media.Imaging should help you both cpu and bandwidth wise compared to your current code. Memory wise I would guess about the same.

    0 讨论(0)
  • 2020-12-02 10:02
    Bitmap scrImg = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    Graphics scr;
    scr.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.PrimaryScreen.Bounds.Size);
    testPictureBox.Image = (Image)scrImg;
    

    I use this code to capture my screen.

    0 讨论(0)
  • 2020-12-02 10:03

    You should be aware for this points:

    • Transport: TCP/binary message encoding will be fastest way to transfer your image data
    • Image capture: you can rely on P/Invoke to access your screen data, as this can be faster and more memory consuming. Some examples: Capturing the Screen Image in C# [P/Invoke], How to take a screen shot using .NET [Managed] and Capturing screenshots using C# (Managed)
    • You should to reduce your image data before send it;
      • choose your image format wisely, as some formats have native compression (as JPG)
      • an example should be Find differences between images C#
      • sending only diff image, you can crop it and just send non-empty areas
    • Try to inspect your WCF messages. This will help you to understand how messages are formatted and will help you to identify how to make that messages smaller.

    Just after passing through all this steps and being satisfied with your final code, you can download VncSharp source code. It implements the RFB Protocol (Wikipedia entry), "a simple protocol for remote access to graphical user interfaces. Because it works at the framebuffer level it is applicable to all windowing systems and applications, including X11, Windows and Macintosh. RFB is the protocol used in VNC (Virtual Network Computing)."

    0 讨论(0)
  • 2020-12-02 10:05

    Check out this: Large Data and Streaming (WCF)

    0 讨论(0)
  • 2020-12-02 10:05
    1. Your solution looks fine to me, but I suggest (as others did) you use tiles and compress the traffic when possible. In addition, I think you should send the entire image once a while, just to be sure that the client's deltas have a common "base".

    2. Perhaps you can use an existing solution for streaming, such as RTP-H263 for video streaming. It works great, it uses compression, and it's well documented and widely used. You can then skip the WCF part and go directly to the streaming part (either over TCP or over UDP). If your solution should go to production, perhaps the H263 streaming approach would be better in terms of responsiveness and network usage.

    0 讨论(0)
  • 2020-12-02 10:10

    I worked on a similar project a while back. This was my general approach:

    • Rasterized the captured bitmap to tiles of 32x32
    • To determine which tiles had changed between frames I used unsafe code to compare them 64-bits at a time
    • On the set of delta tiles I applied one of the PNG filters to improve compressability and had the best results with the Paeth filter
    • Used DeflateStream to compress the filtered deltas
    • Used BinaryMessageEncoding custom binding to the service to transmit the data in Binary in stead of the default Base64 encoded version

    Some client-side considerations. When dealing with large amounts of data being transferred through a WCF service I found that some parameters of the HttpTransportBinding and the XmlDictionaryRenderQuotas were set to pretty conservative values. So you will want to increase them.

    0 讨论(0)
提交回复
热议问题