0

I've made a program which is sending images over TCP sockets, it can be running for a while then always on the server side it has an error deserializing the stream.

Additional information: Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.

The full function which is causing the error is:

private void handleClientThread(TcpClient tcpClient)
{
    while (true)
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        pictureBox1.Image = (Image)binaryFormatter.Deserialize(tcpClient.GetStream()); // this line is the one throwing an exception
        pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
    }

}

The client is sending everything correctly:

private Image TakePicture()
{
    Bitmap bmpScreenCapture = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    Graphics g = Graphics.FromImage(bmpScreenCapture);
    g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, bmpScreenCapture.Size, CopyPixelOperation.SourceCopy);

    return bmpScreenCapture;
}

private void SendPicture()
{
    Image clientPicture = TakePicture();

    BinaryFormatter binaryFormatter = new BinaryFormatter();
    binaryFormatter.Serialize(sharerClient.GetStream(), clientPicture);
}

Could anyone help me with this issue or help me send the images over TCP sockets without it throwing an exceptions.

  • Drop `BinaryFormatter` altogether, and just send the pixel data (or better yet, compressed pixel data, like PNG). `BinaryFormatter` is slow, not interoperable, and is a versioning nightmare - it should have been deprecated long ago. – Lucas Trzesniewski May 01 '16 at 15:20
  • Could you give me an example of how I would send it, I spent around 2 hours trying to get it working without using `BinaryFormatter` to no avail – user6278056 May 01 '16 at 15:28
  • I don't have much time to write an answer right now, but essentially: call [`Bitmap.Save`](https://msdn.microsoft.com/en-us/library/ms142147.aspx), passing it the network stream. You'll probably have to send a header with the image size in bytes first, though, so you could use an intermediary `MemoryStream` for this. On the other side, construct a `Bitmap` using the constructor overload which takes a `Stream` parameter. – Lucas Trzesniewski May 01 '16 at 15:35
  • There's no certainty that the entire image will be received in one piece (infact, it most likely will not). You can get as little as one byte and then have to wait a little to get more (which the NetworkStream _doesn't do_). Implement message framing such as [**length- and header-prefixing**](http://stackoverflow.com/a/35240061/3740093), then when _you know_ you've received the entire image you can deserialize it. – Visual Vincent May 01 '16 at 16:13
  • Visual mind doing it in C#? – user6278056 May 01 '16 at 16:53
  • If you'd read it through you would have seen that there are links both to the C# source code and a C# sample project. :) – Visual Vincent May 01 '16 at 19:19
  • @Lucas Trzesniewski Could you respond to my "answer" – user6278056 May 02 '16 at 13:33

1 Answers1

0
private void SendPicture()
{
    Image clientPicture = TakePicture();
    clientPicture.Save(sharerClient.GetStream(), ImageFormat.Png);
}

I came up with that Lucas Trzesniewski, but how would I do it on the server side?

  • If you mean how you'd receive the image, you could use [**Image.FromStream()**](https://msdn.microsoft.com/en-us/library/93z9ee4x(v=vs.110).aspx). But keep in mind that **you will still** have the issue of only getting a part of the image. You really **must** implement some kind of message framing or else there's only a VERY small chance that it will work, – Visual Vincent May 04 '16 at 23:15