TCP客户端/服务器图像传输

时间:2010-05-07 14:30:02

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

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

客户端代码段



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();
    }

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(); }

服务器片段

非常感谢先进,

5 个答案:

答案 0 :(得分:4)

有一些问题,包括可能正在使用的协议。首先,客户:

  • 如果您需要单张图片,则无需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);
        }
    }
}

答案 1 :(得分:1)

这部分看起来很时髦:

  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”数组,然后继续从流上的左侧构建图像。你刚读入“字节”的字节怎么样?

答案 2 :(得分:1)

我建议你使用这个代码(我自己创建并测试它,它的工作非常完美。):

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   
}

使用此命令将接收到的字节数组转换为图像。

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

这是一个解决方案:

服务器端:

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));