1

我编写了一个由服务器和客户端组成的程序。服务器制作截图桌面,客户端接收截图并显示在表单上。数据传输有问题,我只看到一个小条。我在服务器上发送图像之前检查过。但是,客户端收到错误的图像。怎么了?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)
        {
        }
    }

}

PS Result,编译后的屏幕程序: 点击查看

4

2 回答 2

1

I expect client.ReceiveBufferSize on client side has wrong information I would recomend to read data in loop.

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

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

and save data into the List or memorystream Or may be easier way, before your server send all data, send the size

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

and client can read it first to allocate appropriate buffer. To send and receive particular data type I would recomend build BinaryWriter from your NetworkStream

using (BinaryWriter writer = new BinaryWriter(netstream))
于 2013-04-25T11:09:55.997 回答
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)
        {
        }
    }
于 2013-04-25T15:13:08.437 回答