仅显示图片的一小部分

时间:2013-04-25 09:59:38

标签: c# wpf

我编写了一个包含服务器和客户端的程序。服务器制作屏幕截图桌面,客户端接收屏幕截图并在表单上显示。数据传输存在问题,我只看到一个小条带。我在服务器上发送图像之前检查了一下。但是,客户端收到错误的图像。怎么了? XAML:

<Window x:Class="TestTCP.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="TestTCP" Height="350" Width="525">
<Grid>
    <Image x:Name="img1" Margin="0"/>

</Grid>
</Window>

代码C#:

  public partial class MainWindow : Window
  {
    public MainWindow()
    {
        InitializeComponent();

        Task rec = new Task(WaitClientQuery);
        rec.Start();

        Task tk = new Task(Send);
        tk.Start();
    }

    private void Send()//server part. take screen and send image
    {
        Bitmap temp = CaptureScreen(true);
        MemoryStream ms3 = new MemoryStream();
        BitmapImage image = new BitmapImage();
        byte[] img_byte;
        try
        {
            ((System.Drawing.Bitmap)temp).Save(ms3, System.Drawing.Imaging.ImageFormat.Bmp);
            image.BeginInit();
            ms3.Seek(0, SeekOrigin.Begin);
            image.StreamSource = ms3;
            image.EndInit();

            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(image));
            using (MemoryStream ms = new MemoryStream())
            {
                encoder.Save(ms);
                img_byte = ms.ToArray();
            }

            try
            {

                TcpClient client = new TcpClient("192.168.1.64", 4444);
                NetworkStream netstream = client.GetStream();
                netstream.Write(img_byte, 0, img_byte.Length);
                netstream.Close();
                client.Close();
            }
            catch (Exception)
            {

            }
        }
        catch (Exception ee)
        {

        }
    }

    [StructLayout(LayoutKind.Sequential)]
    struct CURSORINFO
    {
        public Int32 cbSize;
        public Int32 flags;
        public IntPtr hCursor;
        public POINTAPI ptScreenPos;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct POINTAPI
    {
        public int x;
        public int y;
    }

    [DllImport("user32.dll")]
    static extern bool GetCursorInfo(out CURSORINFO pci);

    [DllImport("user32.dll")]
    static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);

    const Int32 CURSOR_SHOWING = 0x00000001;

    public static Bitmap CaptureScreen(bool CaptureMouse)
    {
        Bitmap result = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
       try
        {
            using (Graphics g = Graphics.FromImage(result))
            {
                g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);

                if (CaptureMouse)
                {
                    CURSORINFO pci;
                    pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CURSORINFO));

                    if (GetCursorInfo(out pci))
                    {
                        if (pci.flags == CURSOR_SHOWING)
                        {
                            DrawIcon(g.GetHdc(), pci.ptScreenPos.x, pci.ptScreenPos.y, pci.hCursor);
                            g.ReleaseHdc();
                        }
                    }
                }
            }
        }
        catch
        {
            result = null;
        }

        return result;
    }

    void WaitClientQuery()//receive data(client)
    {
        try
        {
            IPAddress ip ;
            IPAddress.TryParse("192.168.1.64", out ip);
            TcpListener listener = new TcpListener(ip, 4444);
            listener.Start(); 
            while (true)
            {
                TcpClient client = listener.AcceptTcpClient();
                Thread thread = new Thread(new ParameterizedThreadStart(ReadMessage));
                thread.IsBackground = true;
                thread.Start(client);
            }
        }
        catch (Exception ex)
        {
        }
    }

    void ReadMessage(object obj)
    {
        try
        {
            TcpClient client = (TcpClient)obj;
            NetworkStream netstream = client.GetStream();
            byte[] arr = new byte[client.ReceiveBufferSize ];
            int len = netstream.Read(arr, 0, client.ReceiveBufferSize);
            if (len > 0)
            {
                try
                {

                    Action act = delegate
                                     {
                                            MemoryStream strmImg = new MemoryStream(arr);
                                            BitmapImage myBitmapImage = new BitmapImage();
                                            myBitmapImage.BeginInit();
                                            myBitmapImage.StreamSource = strmImg;
                                            myBitmapImage.EndInit();
                                            img1.Source = myBitmapImage;
                                     };
                    this.Dispatcher.BeginInvoke(act);

                }
                catch (Exception ex)
                {
                    string message = ex.Message;
                }

            }
            netstream.Close();
            client.Close(); 
        }
        catch (Exception ex)
        {
        }
    }

}

P.S。结果,编译后的屏幕程序: click to view

2 个答案:

答案 0 :(得分:1)

我希望客户端的client.ReceiveBufferSize有错误的信息 我建议在循环中读取数据。

if(netstream.CanRead)
{
                byte[] myReadBuffer = new byte[1024];
                int numberOfBytesRead = 0;

                do
        {
                     numberOfBytesRead = netstream.Read(myReadBuffer, 0, myReadBuffer.Length);                              
                }
                while(netstream.DataAvailable);
}

并将数据保存到List或memorystream中 或者可能更容易,在服务器发送所有数据之前,发送大小

netstream.Write(img_byte.Length); //does not work with NetworkStream
netstream.Write(img_byte, 0, img_byte.Length);

并且客户端可以先读取它以分配适当的缓冲区。 要发送和接收特定数据类型,我建议 从BinaryWriter

构建NetworkStream
using (BinaryWriter writer = new BinaryWriter(netstream))

答案 1 :(得分:1)

client.ReceiveBufferSize使用默认值的主要根本原因是8192字节,因此客户端将无法接收从服务器传输的足够图像。在我的代码中,我想在客户端看到正确的图像大小,所以我使用BinaryWriter来传输图像的长度。从客户端我使用BinaryReader来读取确切的字节数和图像大小以节省带宽。希望这个帮助

使用Send方法:

TcpClient client = new TcpClient("192.168.1.64", 4444);
 using (NetworkStream netstream = client.GetStream())
 {
     using (BinaryWriter bw = new BinaryWriter(netstream))
     {
        bw.Write(img_byte.Length);
        bw.Write(img_byte, 0, img_byte.Length);
     }

     client.Close();
 }

ReadMessage(object obj)

private void ReadMessage(object obj)
    {
        try
        {
            byte[] arr = null;
            TcpClient client = (TcpClient) obj;
            using (NetworkStream netstream = client.GetStream())
            {
                using (BinaryReader br = new BinaryReader(netstream))
                {
                    var arrLen = new byte[4];
                    br.Read(arrLen, 0, 4);
                    int len = BitConverter.ToInt32(arrLen, 0);
                    if (len > 0)
                    {
                        arr = new byte[len];

                        int read = 0;
                        while (read != len)
                        {
                            read += br.Read(arr, read, arr.Length - read);
                        }
                    }
                }
            }

            if (arr != null && arr.Length > 0)
            {
                try
                {

                    Action act = delegate
                        {
                            MemoryStream strmImg = new MemoryStream(arr);
                            BitmapImage myBitmapImage = new BitmapImage();
                            myBitmapImage.BeginInit();
                            myBitmapImage.StreamSource = strmImg;
                            myBitmapImage.EndInit();
                            img1.Source = myBitmapImage;
                        };
                    this.Dispatcher.BeginInvoke(act);

                }
                catch (Exception ex)
                {
                    string message = ex.Message;
                }

            }

            client.Close();
        }
        catch (Exception ex)
        {
        }
    }