图片框不显示来自TCP套接字的图像

时间:2017-03-29 07:48:34

标签: winforms sockets tcp c#-3.0

我正在开发一个TCP客户端 - 服务器程序,客户端将捕获其截图并通过TCP套接字连续发送到服务器。服务器将在图片框中显示图像。截至目前,客户端和服务器之间的图像传输工作正常,但图像没有显示在图片框中。

服务器端代码:

   private void startListening()
    {

        //label1.Text = "Server is starting...";
        Console.WriteLine("Server is starting...");
        byte[] data = new byte[1024];
        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);

        Socket newsock = new Socket(AddressFamily.InterNetwork,
                        SocketType.Stream, ProtocolType.Tcp);

        newsock.Bind(ipep);
        newsock.Listen(10);
        //label1.Text="Waiting for a client...";

        Socket client = newsock.Accept();
        IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
        //label1.Text = "Connected to client.";

        while (true)
        {
            data = ReceiveVarData(client);
            MemoryStream ms = new MemoryStream(data);
            try
            {
                lock (this)
                {
                    Image img = Image.FromStream(ms);
                    pictureBox1.Image = img;
                    pictureBox1.Invoke((MethodInvoker)delegate
                    {
                        pictureBox1.Refresh();
                    });
                }
            }
            catch (ArgumentException e)
            {
                Console.WriteLine("something broke");
            }


            if (data.Length == 0)
                newsock.Listen(10);
        }
        //Console.WriteLine("Disconnected from {0}", newclient.Address);
        client.Close();
        newsock.Close();
        /////////////////////////////////////////////

    }

    private byte[] ReceiveVarData(Socket client)
    {
        int total = 0;
        int recv;
        byte[] datasize = new byte[4];

        recv = client.Receive(datasize, 0, 4, 0);
        int size = BitConverter.ToInt32(datasize, 0);
        int dataleft = size;
        byte[] data = new byte[size];


        while (total < size)
        {
            recv = client.Receive(data, total, dataleft, 0);
            if (recv == 0)
            {
                break;
            }
            total += recv;
            dataleft -= recv;
        }
        return data;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var t = new Thread(startListening);
        t.IsBackground = true;
        t.Start();
    }

客户端代码:

    static void Main(string[] args)
    {
        byte[] data = new byte[1024];
        int sent;
        IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);

        Socket server = new Socket(AddressFamily.InterNetwork,
                        SocketType.Stream, ProtocolType.Tcp);

        try
        {
            server.Connect(ipep);
        }
        catch (SocketException e)
        {
            Console.WriteLine("Unable to connect to server.");
            Console.WriteLine(e.ToString());
            Console.ReadLine();
        }
        while (true)
        {

            Bitmap bmp = captureImage();

            MemoryStream ms = new MemoryStream();
            // Save to memory using the Jpeg format
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

            // read to end
            byte[] bmpBytes = ms.ToArray();
            bmp.Dispose();
            ms.Close();

            sent = SendVarData(server, bmpBytes);

            //Console.WriteLine("Disconnecting from server...");
        }

    }

    private static Bitmap captureImage()
    {
        Bitmap bmpScreenshot = null;
        try
        {
            //Create a new bitmap.
            bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                           Screen.PrimaryScreen.Bounds.Height,
                                           PixelFormat.Format32bppArgb);

        }
        catch (Exception ex)
        {
            Console.WriteLine("Image covertion exception: " + ex);
        }
        return bmpScreenshot;
    }

    private static int SendVarData(Socket s, byte[] data)
    {
        int total = 0;
        int size = data.Length;
        int dataleft = size;
        int sent;

        byte[] datasize = new byte[4];
        datasize = BitConverter.GetBytes(size);
        sent = s.Send(datasize);

        while (total < size)
        {
            sent = s.Send(data, total, dataleft, SocketFlags.None);
            total += sent;
            dataleft -= sent;
        }
        return total;
    }
}

1 个答案:

答案 0 :(得分:0)

我认为您的问题可能是您尝试从网络线程中操纵GUI组件,该代码:

lock (this)
{
   Image img = Image.FromStream(ms);
   pictureBox1.Image = img; // Access from network thread to GUI component
   pictureBox1.Invoke((MethodInvoker)delegate
   {
       pictureBox1.Refresh();
   });
}

您应该执行以下操作:

// No lock here - it's not needed
// The image data is created on the network thread, it get's captured
// by the closure and will only get applied on the UI thread
// If this also doesn't work you might try to capturing the MemoryStream
// and transfer that to the GUI thread
Image img = Image.FromStream(ms);    
pictureBox1.Invoke((MethodInvoker)delegate
{
   pictureBox1.Image = img;
   pictureBox1.Refresh();
});

我也发现了一些小问题:

  • 您没有完全处理endOfStream(recv == 0)。在这种情况下,您会尝试将未完全接收的图像传递给GUI,而不是停止接收。
  • 您不会从流中捕获异常并在发生情况时进行清理。这意味着您的接收线程可能会崩溃。考虑使用try / catch / finally。和/或管理套接字生命周期的using
  • 您没有检查是否已收到所有字节,并且在发送/接收4个字节字节时已发送。