只显示图片的一小部分

问题描述:

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

} 

附:因此,屏幕的程序编译后: click to view

+0

当你说 “小条” 究竟是什么意思呢?你的意思是图像只是一行像素? – 2013-04-25 10:22:58

+0

这个问题的根本原因是'client.ReceiveBufferSize'使用默认值8192,所以你的图片只能从服务器接收一小部分。 – 2013-04-25 11:20:46

+0

我想为这个问题+1,因为许多使用'client.ReceiveBufferSize'在其他地方问题。 – 2013-04-25 15:24:49

主根发送和接收特定数据类型我会建议 构建BinaryWriter使用默认值是8192字节导致client.ReceiveBufferSize,所以客户端将无法接收已经从服务器传输足够的图像。在我的代码中,我希望在客户端看到正确的图像大小,因此我使用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) 
     { 
     } 
    } 
+0

谢谢,我以前也有这个问题。 – 2013-04-26 03:03:01

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

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

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

和数据保存到列表或MemoryStream的 或可能是更简单的方法,你的服务器发送的所有数据之前,发送大小

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

和客户端可以先阅读它来分配适当的缓冲。 要从NetworkStream

using (BinaryWriter writer = new BinaryWriter(netstream)) 
+0

我就是你制造的。确实,客户端有错误的信息(服务器大小:181021字节)。但是当我使用你的方法来接收字节时,客户端的缓冲区大小为:181248字节。我在debbager看到,数组的开始和结束都不是相等的! – 2013-04-25 12:00:58

+0

循环也服务器写入,tcp将等待接收,所以你可以看到在调试中发生了什么。我了解结束181248多1024表示最后读取shold返回numberOfBytesRead小于1024 – user2136076 2013-04-25 12:11:17

+0

请参阅下面的代码帖子以正确地获取服务器的图像传输大小超过图像的硬代码长度。 – 2013-04-25 16:23:32