简体   繁体   中英

Read First 6 Bytes From NetworkStream?

I am sending an image(a screenshot, particularly) via a tcpclient/networkstream. To read the image bytes properly on the receiving end, I need to know the length of the image. What I intend to do is save the first 6 bytes of the buffer for the image size(since it seems to never exceed 6 numbers), and then from thereon have the rest of the buffer as the image. The problem I am having is I am not able to read only the first 6 bytes.

Server Code

       int data = 0;

        byte[] readBuffer = new byte[getSelectedClient().ReceiveBufferSize];

        **data = stream.Read(readBuffer, 0, 5, readBuffer.Length);** <-- sort of thing im trying to do

        string pictureSize = Encoding.ASCII.GetString(readBuffer, 0, data);

        Console.WriteLine(pictureSize); //for debugging purposes

        string x = new Random().Next().ToString();

        FileStream f = new FileStream(x + ".bmp", FileMode.Create, FileAccess.Write);

        while (new FileInfo(x + ".bmp").Length != Convert.ToInt32(pictureSize))
        {
            **data = stream.Read(readBuffer, 6, readBuffer.Length);** <-- then it would read from the 6th byte, which would be the start of the image
            f.Write(readBuffer, 0, data);
        }

        f.Close();

        Process.Start(x + ".bmp");

        screenShotBTN.Enabled = true;

Client Code

MemoryStream ms = new MemoryStream();
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
               writeToStream(combineBytes(Encoding.ASCII.GetBytes(ms.Length.ToString()), ms.ToArray()));
ms.Close();


public static byte[] combineBytes(byte[] b1, byte[] b2)
    {
        byte[] b3 = new byte[b1.Length + b2.Length];
        Array.Copy(b1, 0, b3, 0, b1.Length);
        Array.Copy(b2, 0, b3, b1.Length, b2.Length);
        return b3;
    }

What you are implementing is Length Prefixed messaging.

Things to remember are that when you are reading from a network stream, you will not necessarily receive all the bytes that you are looking for immediately (most times when you are testing locally everything will, but you need to program for the possibility you'll only receive 1 byte at the worst case).

Therefore you should go into a state (awaitinglength, awaitingpayload). Then you commence reading byte(s) while in the awaiting length, then build up that data in a buffer. Once you have your length (6 bytes in your case), then you can switch state to awaitingpayload, then read this into your secondary buffer until you have the full payload and then you are good to go.

It might be worthwhile to have a read of Stephen Cleary's articles on message framing. I learn't a lot about networking through reading these.

http://blog.stephencleary.com/2009/04/sample-code-length-prefix-message.html

I solved the issue on my own.

Server

int data = 0;

byte[] readBuffer = new byte[getSelectedClient().ReceiveBufferSize];

data = stream.Read(readBuffer, 0, 6); //only read first 6

string pictureSize = Encoding.ASCII.GetString(readBuffer, 0, data);

Console.WriteLine(pictureSize); //for debugging purposes

string x = new Random().Next().ToString();

FileStream f = new FileStream(x + ".bmp", FileMode.Create, FileAccess.Write);

while (new FileInfo(x + ".bmp").Length != Convert.ToInt32(pictureSize))
{
    data = stream.Read(readBuffer, 0, readBuffer.Length); 
    f.Write(readBuffer, 0, data);
}

f.Close();

Process.Start(x + ".bmp");

screenShotBTN.Enabled = true;

Client code

MemoryStream ms = new MemoryStream();
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
Console.WriteLine(ms.Length.ToString());
writeToStream(combineBytes(Encoding.ASCII.GetBytes(ms.Length.ToString()), ms.ToArray()));
ms.Close();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM