ByoTic
ByoTic

Reputation: 333

TCP sending images client and server

I have a client application and a server application. The client application activates this function every 40 milliseconds: *Note that nstream is a NetworkStream instance.

private void SendScreen(NetworkStream nstream)
    {
        StreamWriter writer = new StreamWriter(nstream);
        ScreenCapture sc = new ScreenCapture();
        System.Drawing.Image img = sc.CaptureScreen();
        MemoryStream ms = new MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
        byte[] buffer = new byte[ms.Length];
        ms.Seek(0, SeekOrigin.Begin);
        ms.Read(buffer, 0, buffer.Length);
        Console.WriteLine(buffer.Length);
        writer.WriteLine(buffer.Length);
        writer.Flush();
        nstream.Write(buffer, 0, buffer.Length);
    }

and this is the server application code for receiving the image:

private async void ShowImage()
    {
        while (true)
        {
            string num = await reader.ReadLineAsync();
            Console.WriteLine(num);
            int ctBytes = int.Parse(num);
            byte[] buffer = new byte[ctBytes];
            await stream.ReadAsync(buffer, 0, buffer.Length);
            MemoryStream ms = new MemoryStream(buffer);
            Image img = Image.FromStream(ms);
            Bitmap bmp = new Bitmap(img);
            this.Height = bmp.Height;
            this.Width = bmp.Width;
            this.BackgroundImage = bmp;
        }
    }

I can't think of any parts that disturbs these actions. In the first iteration of the server application, everything works (although I see black screen instead of the screenshot - but the number of bytes sent and received- matches.) At the second iteration when I writeline num, it shows jibberish and then stops (because it cannot be parsed to int).

Upvotes: 0

Views: 2306

Answers (1)

MrPaulch
MrPaulch

Reputation: 1418

Essentially I suspect you have a sync problem as I had, when I attempted to reproduce your problem (successfully).

Be it a Header or a single Integer that announces an upcomming Bitmap transmission. It's all terribly easy to get out of sync.

Unless you want to dive into network synchronization and flow control I recommend to use a single TransmissionObject for every transmission between the server and the client (and maybe another vice versa)

That Object has the potential to store any data that has to be transmitted. (via inheritance)

Finally when putting the Object on the network stream you may use any consistent Serializer

The Serializer does all the work of syncing up the information to where it is needed (Meta information like length and finally the content aswell)


Well in my repro project I came up with this Class to hold the Bitmap.

As an example to how to use it on the Server:

    public void Send(Bitmap bmp)
    {
        // prepare Bitmap
        BitmapTransmission bt = new BitmapTransmission(bmp);

        // try transmitting the object
        try
        {
            // lock to exclude other Threads of using the stream
            lock (m_objSendLock)
            {
                bt.Send(m_stream);                    
            }
        } 
        catch (BitmapTransmissionException ex) 
        { // will catch any exception thrown in bt.Send(...)
            Debug.Print("BitmapHeaderException: " + ex.Message);
            ///BitmapTransmissionException provides a Property `CloseConnection`
            /// it will inform you whether the Exception is recoverable
        }
    }

Where m_objSendLock is an Object to prevend concurrent access on the network stream. m_stream is the NetworkStream connected to the Client. Echo is a logging mechanism.

The client may receive such transmissions via

  public void Receive() {
         BitmapTransmission bt = bt.Receive(m_stream);
         // check for exceptions maybe?

         pictureBox1.Image = bt.Bitmap;
  }

Where as again m_stream it the NetworkStream connected to the Server.

If you want to have a look at the (messy but working) repro project do tell so.

Upvotes: 1

Related Questions