【问题标题】:TCP Client/Server Image TransferTCP 客户端/服务器图像传输
【发布时间】:2010-05-07 14:30:02
【问题描述】:

我正在尝试使用 TCP 套接字发送图像。客户端连接到服务器没有任何问题并开始接收数据。问题是当我尝试使用 FromStream() 方法将流转换为图像时,我得到了 OutOfMemory 异常。谁能帮我吗?真的很重要!!这是代码;

客户端 sn-p



private void btnConnect_Click(object sender, EventArgs e)
        {
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            TcpClient client = new TcpClient();

        client.Connect(ipAddress, 9500);
        NetworkStream nNetStream = client.GetStream();

        while (client.Connected)
        {
            lblStatus.Text = "Connected...";
            byte[] bytes = new byte[client.ReceiveBufferSize];
            int i;
            if (nNetStream.CanRead)
            {
                nNetStream.Read(bytes, 0, bytes.Length);  

                Image returnImage = Image.FromStream(nNetStream); //exception occurs here
                pictureBox1.Image = returnImage;
            }
            else
            {
                client.Close();
                nNetStream.Close();
            }


        }
        client.Close();
    }

服务器 sn-p


try
            {
                IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
                TcpListener server = new TcpListener(ipAddress, 9500);
                server.Start();
                Console.WriteLine("Waiting for client to connect...");

                while (true)
                {
                    if (server.Pending())
                    {
                        Bitmap tImage = new Bitmap(Image URL goes here);
                        byte[] bStream = ImageToByte(tImage);

                        while (true)
                        {
                            TcpClient client = server.AcceptTcpClient();
                            Console.WriteLine("Connected");
                            while (client.Connected)
                            {
                                NetworkStream nStream = client.GetStream();
                                nStream.Write(bStream, 0, bStream.Length);
                            }
                        }
                    }
                }

            }


            catch (SocketException e1)
            {
                Console.WriteLine("SocketException: " + e1);
            }
        }
        static byte[] ImageToByte(System.Drawing.Image iImage)
        {
            MemoryStream mMemoryStream = new MemoryStream();
            iImage.Save(mMemoryStream, System.Drawing.Imaging.ImageFormat.Gif);
            return mMemoryStream.ToArray();
        }

非常感谢,

【问题讨论】:

    标签: c# .net visual-studio sockets network-programming


    【解决方案1】:

    有几处错误,可能包括您正在使用的协议。一、客户端:

    • 如果您期望单个图像,则不需要 while 循环
    • 您的客户端首先执行Read,它将一些信息从服务器读取到缓冲区,然后它调用Image.FromStream(nNetStream),它将读取不完整的数据。
    • 无论何时从流中读取数据,请记住单个Read 调用不能保证填满缓冲区。它可以返回 0 和缓冲区大小之间的任意数量的字节。如果它返回 0,则表示没有更多内容可读取。在您的情况下,这也意味着您的客户端目前无法知道从服务器读取多少内容。这里的一个解决方案是让服务器将图像的长度作为第一条信息发送。另一种解决方案是让服务器在发送信息后断开客户端的连接。在您的情况下这可能是可以接受的,但如果您需要持久连接(例如客户端的池连接),它将不起作用。

    客户端应该看起来像这样(假设服务器在发送数据后会断开它):

    IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
    using (TcpClient client = new TcpClient())
    {
        client.Connect(ipAddress, 9500);
        lblStatus.Text = "Connected...";
    
        NetworkStream nNetStream = client.GetStream();
        Image returnImage = Image.FromStream(nNetStream);
        pictureBox1.Image = returnImage;
    }
    

    接下来,服务器:

    • 代替Pending,您可以简单地接受客户端
    • 服务器一遍又一遍地将流发送到同一个客户端,直到它们断开连接。而是只发送一次。

    服务器循环应该如下所示:

    Bitmap tImage = new Bitmap(Image URL goes here);
    byte[] bStream = ImageToByte(tImage);
    
    while (true)
    {
        // The 'using' here will call Dispose on the client after data is sent.
        // This will disconnect the client
        using (TcpClient client = server.AcceptTcpClient())
        {
            Console.WriteLine("Connected");
            NetworkStream nStream = client.GetStream();
    
            try
            {
                nStream.Write(bStream, 0, bStream.Length);
            }
            catch (SocketException e1)
            {
                Console.WriteLine("SocketException: " + e1);
            }
        }
    }
    

    【讨论】:

    • 非常感谢您的代码,Bojan Resnik!感谢您的良好解释,我也设法在我的代码中找到了错误。但是,我希望看到一个示例,说明如何使用持久连接来执行相同操作。我理解您必须通​​知客户端要发送多少字节的问题,但是谁能通过扩展 Bojan 的代码来帮助我们理解?
    【解决方案2】:

    这部分在我看来很时髦:

      byte[] bytes = new byte[client.ReceiveBufferSize]; 
      int i; 
      if (nNetStream.CanRead) 
      { 
        nNetStream.Read(bytes, 0, bytes.Length);   
    
        Image returnImage = Image.FromStream(nNetStream); //exception occurs here 
    

    首先将 client.ReceiveBufferSize 字节读入“bytes”数组,然后继续从流中剩余的内容构造图像。你刚刚读入“字节”的字节呢?

    【讨论】:

    • 如果没有nNetStream.Read(bytes, 0, bytes.Length);,它对他也有用
    【解决方案3】:

    我建议您使用此代码(我自己创建并测试了它,它运行完美。):

    public void Bitmap ConvertByteArrayToBitmap(byte[] receivedBytes)
    {
       MemoryStream ms = new MemoryStream(receivedBytes);
       return new Bitmap(ms, System.Drawing.Imaging.ImageFormat.Png); // I recomend you to use png format   
    }
    

    使用它来将接收到的 byteArray 转换为图像。

    【讨论】:

      【解决方案4】:

      您的服务器似乎一遍又一遍地发送图像:

      while (client.Connected)
      {
          NetworkStream nStream = client.GetStream();
          nStream.Write(bStream, 0, bStream.Length);
      }
      

      如果服务器可以足够快地发送数据,客户端可能会继续接收它。

      【讨论】:

      • 只发送一次图像数据,而不是在一个while循环中。例如,将“while”更改为“if”。
      【解决方案5】:

      这里有一个解决方案:

      服务器端:

      tImage.Save(new NetworkStream(client), System.Drawing.Imaging.ImageFormat.Png);
      

      客户端:

      byte[] b = new byte[data.ReceiveBufferSize];
      client.Receive(b);
      MemoryStream ms = new MemoryStream(b);
      Image receivedImag = Image.FromStream(ms);
      

      或:

      Image receivedImag = Image.FromStream(new NetworkStream(client));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-25
        • 2019-03-12
        • 2013-08-20
        • 2012-01-04
        • 2013-02-17
        相关资源
        最近更新 更多