5

i'm trying to learn to use sockets in c# and i've a doubt, i'm using a code something like this:

byte[] data = new byte[64]; 
int length = 0;
length = sock.Receive(data);
//more code...

So, the byte[] data is filled with the recived data and the left space in the array is filled with 0s, Is the byte[] allocated into memory completely (all 64bytes)? If it's so, is there a way to make the byte[] the same size as the actual sent data?

3
  • 1
    You can check sock.Available to see how much data has already come in from the network. Note, you may get more data later on though. Commented Dec 15, 2015 at 19:10
  • Yes, the 64 bytes are all allocated. They are allocated before the receive call, so how could anyone know what the actual size of the data will be? It would be like cutting a piece of twine to the right length for wrapping a package you've never seen. You'd need a crystal ball. Commented Dec 15, 2015 at 19:14
  • @ebyrob Thank. This .Available() method works for me. Commented Jun 16, 2020 at 7:20

3 Answers 3

4

You can check sock.Available to see what has already come in. (so far)

byte[] data = new byte[sock.Available]; 
int length = sock.Receive(data);
//more code...

Note: Since you may or may not know what is coming in next on the network it usually makes more sense to read only a header (with size info) first or to allocate more space than necessary, and call .Recieve() multiple times until the end of a record is reached.

Note: This code assumes you already know there is some data to receive and you've waited long enough for some useful amount of data to be ready.

If you do choose to use length headers, .Available can help you avoid reading a partial header and having to re-assemble it which is nice. (Only large messages may need manual reassembly in that case)

Sign up to request clarification or add additional context in comments.

8 Comments

Not sure how this helps. What if Available is zero?
@usr Then there's no data to read... Also, available bytes may change between read and check.
Oh, thats exactly what i was looking for, i didn't know available was that :P, Thank you.
If Available is zero there might still be data to read later. This does not help @user3324670. Available is useless for almost any purpose.
This code assumes you already ... waited long enough for some useful amount of data to be ready And how is he going to do that?
|
2

You simply need to use the return value from Receive to understand how much data has arrived. You can shorten the buffer using Array.Resize if you want but that normally would be a sign that something is wrong.

Also note, that TCP is a stream of bytes and does not preserve message boundaries.

5 Comments

I've tried using "byte[] data = new byte[1048576]; " and the CPU usage went from 0,4 to 2,7 and the memory from 6mb to 20mb, so it is allocated. The problem is that i don't know what's the size of the received data until i do receive it, and I need to have a byte[] of at least the size of the sent data before i receive it(or i don't know how to do it either way). The only solution i can imagine is making the client send a max number of data and not more.
@user3324670 Knowing what to expect from the client is a big part of network programming. Also, you can read only part of the available data, and then read again to get the rest. (under and over reading is OK, just re-assemble the message once you have it)
The only way to know how much is coming is to have the other side tell you, for example by sending an integer with how many bytes they will now send. This is a common approach.
Regarding allocation, why would it not be allocated? It's a normal array. Using it with sockets does not make it special.
In any case you will need to loop until you have all data you want. Use BinaryReader to automate some of that away.
2

As noted normally read may return fewer bytes then it was told. See a workaround function below which ensures it reads as many bytes as it was told - basically size of the passed buffer. Function is from here.

/// Reads data into a complete array, throwing an EndOfStreamException
/// if the stream runs out of data first, or if an IOException
/// naturally occurs.
/// </summary>
/// <param name="stream">The stream to read data from</param>
/// <param name="data">The array to read bytes into. The array
/// will be completely filled from the stream, so an appropriate
/// size must be given.</param>
public static void ReadWholeArray (Stream stream, byte[] data)
{
    int offset=0;
    int remaining = data.Length;
    while (remaining > 0)
    {
        int read = stream.Read(data, offset, remaining);
        if (read <= 0)
            throw new EndOfStreamException 
                (String.Format("End of stream reached with {0} bytes left to read", remaining));
        remaining -= read;
        offset += read;
    }
}

You can use this method first to read say a 2 byte integer which should represent the number of bytes that will follow. Then you read once again however now read as many bytes as specified in that two byte integer.

But for this to work, clearly the sender first has to send a two byte integer which represents length of data that will follow - and then the data itself.

So basically you call above function on a byte array of size two first (to get data length), and then on a byte array with size as indicated in that 2 byte integer (to get data).

You can use this to read from NetworkStream. Some more reading on this topic.

6 Comments

I might something like this, just reading a 2byte and converting it to integer and then reading the size that was sent
@user3324670: Yes you should go that way; you can use above function for reading
I'm a bit worried abuout this though, if someone would sent a size that's not correct everything would mess up (I guess that if I want a server to be secure i've to care about many other things).
@user3324670: Yes that is a security issue now and you need to address that differently
I have no idea about how would i do that, anyway i'm sure i'm doing many other things wrong, at least i'm learning
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.