TCP / TCP client image transmission

I am trying to send an image using a TCP socket. The client connects to the server without any problems and starts receiving data. The problem is that when I try to convert a stream to an image using the FromStream () method, I get an OutOfMemory exception. Can anyone help me? Very important! Here is the code:

client snippet



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

      





>



server fragment


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


      

Thanks a lot in advanced,

+2


a source to share


5 answers


There are a couple of bugs, including perhaps the protocol you are using. First, the client:

  • If you are expecting a single image, there is no need for a loop while

  • First, the client executes Read

    , which reads some information from the server into a buffer, and then calls Image.FromStream(nNetStream)

    , which will read the incomplete data.
  • Whenever you read a stream, keep in mind that a single call Read

    does not guarantee that your buffer is full. It can return any number of bytes between 0 and your buffer size. If it returns 0, then there is nothing more to read. In your case, this also means that your client does not currently know how much to read from the server. The solution here is for the server to send the length of the image as the first piece of information. Another solution would be to shutdown the server after sending this information. This may be acceptable in your case, but it won't work if you need persistent connections (for example, client-side pooled connections).

The client should look something like this (assuming the server will shut it down after sending the data):

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

      



Then the server:

  • Instead, Pending

    you can just accept the client
  • The server sends the stream over and over to the same client until it disconnects. Instead, send it only once.

The server loop should look something like this:

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

      

+4


a source


This part looks scared to me:

  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 

      



First, you read the client.ReceiveBufferSize bytes into the "bytes" array, and then move on to building an image from what's left in the stream. How about the bytes you just read in "bytes"?

+1


a source


I recommend you use this code (I created it myself and tested it and it works great.):

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   
}

      

Use this to convert the resulting byteArray to an image.

+1


a source


Your server seems to be sending the image over and over again:

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

      

If the server can send data fast enough, the client will probably continue to receive it.

0


a source


Here's the solution:

Server side:

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

      

Cleand's side:

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

      

or:

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

      

0


a source







All Articles