TCPClient.Read Reading in chunks of as low as 4 bytes

I fully understand the fact that I cannot read the max allotted if the data has not arrived yet. But is it really reasonable to read at a speed of 4 bytes? I mean if I am receiving a an image of 100000 bytes that would take way too long.

Is there an obvious issue with out I am receiving or sending my image?

**** To clarify: The below rLength changes every time sometimes I would only receive 4 bytes and only 4 bytes within that while loop other times I get 3000 and only 3000 in the loop. I am pretty sure there is more data but it seems to be stuck at reading only x amount per loop****

Here is the receiving code on server side

int totalBuffer, totalRecieved = 0;
byte[] totalBufferByte = new byte[4];
byte[] buffer = new byte[0];
byte[] tbuffer;
int rLength, prevLength;
stream.Read(totalBufferByte, 0, totalBufferByte.Length);
totalBuffer = BitConverter.ToInt32(totalBufferByte, 0);
byte[] buf = new byte[8192];
while (totalBuffer > totalRecieved)
{

    rLength = stream.Read(buf, 0, buf.Length);
    totalRecieved = rLength + totalRecieved;
    Console.WriteLine("totalRecieved len: " + totalRecieved + " " + totalBuffer + " " + rLength + " " + buf.Length);
    if (rLength < buf.Length)
    {
        byte[] temp = new byte[rLength];
        Array.Copy(buf, temp, rLength);
        buf = temp;
    }
    prevLength = buffer.Length;
    tbuffer = buffer;
    buffer = new byte[buffer.Length + rLength];
    Array.Copy(tbuffer, buffer, tbuffer.Length);
    buf.CopyTo(buffer, prevLength);
}

Here is the sending code

public void SendResponse(int command, Object[] args)
{
    if (ClientSocket == null)
    {
        Console.WriteLine("Command: ClientSocket");
        return;
    }
    var serverStream = this.ClientSocket.GetStream();
    if (!serverStream.CanRead || !serverStream.CanWrite)
    {
        Console.WriteLine("Command: serverStream Error");
        return;
    }
    byte[] toSend = null;
    switch (command)
    {
        // 0 - genneral, 1 - handshake response
        case 0:
            toSend = Encoding.ASCII.GetBytes(args[0].ToString());
            break;
        case 1:
            Rectangle bounds = Screen.GetBounds(Point.Empty);
            using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
                }
                toSend = ImageToByte(bitmap);
            }
            break;
    }

    try
    {
        byte[] bufferedToSend = new byte[toSend.Length + 4];
        byte[] lengthOfSend = BitConverter.GetBytes(toSend.Length);
        Array.Copy(lengthOfSend, bufferedToSend, 4);
        toSend.CopyTo(bufferedToSend, 4);
        serverStream.Write(bufferedToSend, 0, bufferedToSend.Length);
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}
Jon Skeet
people
quotationmark

This is at least part of the problem:

rLength = stream.Read(buf, 0, buf.Length);
...
if (rLength < buf.Length)
{
    byte[] temp = new byte[rLength];
    Array.Copy(buf, temp, rLength);
    buf = temp;
}

Basically you're limiting your next read to at most the size of your previous read.

It's not clear what you're really trying to do, but it sounds like you should have something like:

byte[] lengthBuffer = new byte[4];
int lengthRead = stream.Read(lengthBuffer, 0, lengthBuffer.Length);
// TODO: Throw or loop if you haven't read 4 bytes...
int length = BitConverter.ToInt32(totalBufferByte, 0);
byte[] buffer = new byte[length];
int lengthRead = 0;
while (lengthRead < length)
{
    int chunkRead = stream.Read(buffer, lengthRead,
                                length - lengthRead);
    if (chunkRead == 0)
    {
        throw new IOException(
            "Stream ended after reading {0} out of {1} bytes",
            lengthRead, length);
    }
    lengthRead += chunkRead;
}

In other words, you should always ask to read "however much data is left" - without ever copying the data into new separate byte arrays.

people

See more on this question at Stackoverflow