TCP Client/Server Image Transfer

27,712

Solution 1

There are a couple of things wrong, including, possibly the protocol you are using. First, the client:

  • If you expect a single image, there is no need for the while loop
  • Your client first does a Read which reads some information from the server into the buffer, and then it calls Image.FromStream(nNetStream) which will read incomplete data.
  • Whenever you read from a stream, keep in mind that a single Read call is not guaranteed to fill your buffer. It can return any number of bytes between 0 and your buffer size. If it returns 0, it means there is no more to read. In your case this also means that your client currently has no way of knowing how much to read from the server. A solution here is to have the server send the length of the image as the first piece of information. Another solution would be to have the server disconnect the client after it has sent the information. This may be acceptable in your case, but it will not work if you need persistent connections (e.g. pooled connections on client side).

The client should look something like this (assuming the server will disconnect it after it sends 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;
}

Next, the server:

  • Instead of Pending, you can simply accept the client
  • The server sends the stream over and over again to the same client, until they disconnect. 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);
        }
    }
}

Solution 2

This part looks funky 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 client.ReceiveBufferSize bytes into the "bytes" array, and then you proceed to construct the image from what's left on the stream. What about the bytes you just read into "bytes"?

Solution 3

I recomend you to use this code(I've created it by myself and tested it and it works perfect.):

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 received byteArray to an image.

Share:
27,712
Penguen
Author by

Penguen

Updated on June 17, 2020

Comments

  • Penguen
    Penguen almost 4 years

    I'm trying to send an image using a TCP socket. The client connects to the server without any problems and start to receive the data. The problem is when I try to convert the stream to an image using FromStream() method, I get an OutOfMemory Exception. Can anyone help me out? Really 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 snippet

    
    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,