Network Stream => Memory Stream => Image

Master Zero

Well-known member
Joined
Sep 10, 2005
Messages
51
Programming Experience
Beginner
I am trying to send a large image through TCP sockets, but I seem to have hit a dead end. I am writing the network stream into a memory stream and from there I am try to create an image from that stream but I keep getting this exception:
A generic error occurred in GDI+.
I don’t understand what’s causing it or how to remedy it. I have search all over the net to no avail.

Does anyone have a work around or solution?

VB.NET:
Private Sub AcceptData(ByVal ar As IAsyncResult)
        'Dim client As Net.Sockets.TcpClient = CType(ar.AsyncState, Net.Sockets.TcpClient)
        client.GetStream.EndRead(ar)

        'If numOfBytesRead = 0 Then End

        ' Create a memory stream to hold the bytes
        Dim mem As New IO.MemoryStream()

        Do
            mem.Write(buffer, 0, buffer.Length)
            client.GetStream.Read(buffer, 0, buffer.Length)
        Loop Until client.GetStream.DataAvailable = False

        Dim img As New Bitmap(mem)
        ' Change the picture
        UpdateImage(img)

        client.GetStream.BeginRead(buffer, 0, client.ReceiveBufferSize, _
                                       AddressOf AcceptData, client)
    End Sub

The error happened when creating the BitMap from the memory stream:
VB.NET:
Dim img As New Bitmap(mem)
 
mem.Write changes the Position, which is where Bitmap starts reading. Set Position to 0 before reading into bitmap. If problem persist you probably don't have the exact image byte set.
 
Thank you, you were right about the image size not being the same. I can’t believe I did not pick it up. I guess client.GetStream.DataAvailable = False is unreliable for data transfer. So here is the new code incase anyone is interested, and for future reference:

VB.NET:
    Private Sub AcceptData(ByVal ar As IAsyncResult)
        ' Create a memory stream to hold the bytes
        Dim mem As New IO.MemoryStream()
        Dim totalBytesRead, numOfBytesRead, size As Integer
        totalBytesRead = numOfBytesRead = 0

        'Dim client As Net.Sockets.TcpClient = CType(ar.AsyncState, Net.Sockets.TcpClient)
        numOfBytesRead = client.GetStream.EndRead(ar)

        'If numOfBytesRead = 0 Then End

        ' Get header information
        size = System.Text.Encoding.ASCII.GetString(buffer, 0, numOfBytesRead)

        Do ' Get Image
            numOfBytesRead = client.GetStream.Read(buffer, 0, buffer.Length)
            mem.Write(buffer, 0, numOfBytesRead)
            totalBytesRead += numOfBytesRead
        Loop Until (totalBytesRead >= size)

        ' Change the picture
        Dim img As New Bitmap(mem)
        UpdateImage(img)

        client.GetStream.BeginRead(buffer, 0, client.ReceiveBufferSize, _
                                       AddressOf AcceptData, client)
    End Sub
 
Good.
Position, which is where Bitmap starts reading
well, it doesn't apparently, I'm sure I've seen that before, too, resulting in same error message :cool:
Master Zero said:
I guess client.GetStream.DataAvailable = False is unreliable for data transfer.
It is not unreliable, but it could temporarily report unavailable while buffers are filling, so stopping read at that point is not reliable if you're not sure that is where expected data ends. Looking at your code I can't actually figure out how you control data transfer.. :eek:
 
The part you said about the position is correct, but that is before reading the stream into a buffer. I ran into that error.

That code is just the receiving end, so it is not actually sending anything. After saving the image into a memory stream, I call this method to send it:

VB.NET:
Public Sub SendData(ByVal data As IO.Stream)
        Try
            ' Reset the seek position
            data.Position = 0

            ' Send header information
            ftpClient.GetStream.Write(System.Text.Encoding.ASCII.GetBytes(data.Length.ToString), _
                                      0, data.Length.ToString.Length)

            ' Read and send data
            While (data.Read(dataBuffer, 0, dataBuffer.Length))
                ftpClient.GetStream.Write(dataBuffer, 0, dataBuffer.Length)
            End While
        Catch ex As Exception
            RaiseEvent ReceivedError(ex.Message)
        End Try
    End Sub

My code starts from an asynchronous connection, to a synchronous (with loop), and back again (after exiting loop).
 
Last edited:
OK, so you write x bytes to the stream where the first y number of bytes signifies the length of the remaining data. You have two unknown both of variable length, and they are sent together as a continuous stream - bad protocol! Why not send the always 8 bytes Stream.Length (Long data type as bytes), that way the receiver know that the first 8 bytes is the length, even if 8000 bytes are read each buffer.
 
Somehow you lost me…lol. I thought I was sending them as bytes (or an array of bytes) using the ASCII.GetBytes() function; can you please explain further, maybe showing me an example of exactly what you mean, if it’s not too much trouble?

In my code, I figured that since I started out as an asynchronous network connection, that when the code first entered the callback function, it would be because the length of the incoming data following it has been sent, thus I set the first few bytes read to the variable size. Then I collect the rest, the real data, with a loop.
 
ascii string "1" = bytes {49} length 1
ascii string "12" = bytes {49,50} length 2
ascii string "1234" = bytes {49,50,51,52} length 4
Long 1 = bytes {1,0,0,0,0,0,0,0} length 8
Long 12 = bytes {12,0,0,0,0,0,0,0} length 8
Long 1234 = bytes {210,4,0,0,0,0,0,0} length 8
you see?

If you write 5 bytes then 5 bytes to the networkstream most likely receiver will get 10 bytes in one buffer, not 5 bytes then 5 bytes.
 
Yes, I understand, so what you’re saying is that the being of the file and the header info might be read into one buffer, thus corrupting the whole process. I’ll try and redesign it. Thank you, for the explanation.
 
Back
Top