Main Site Documentation

Receive message using Sockets?


#1

Hi there all, I wrote the following function:

        private String readMessage(Socket myScoket)
        {
            int totalread = 0, currentread = 0;
            byte[] sizeinfo = new byte[1024];
            currentread = totalread = myScoket.Receive(sizeinfo, 1024,
            SocketFlags.None);
            currentread = myScoket.Receive(sizeinfo, totalread,
            sizeinfo.Length - totalread, SocketFlags.None);
            String message= new String(System.Text.Encoding.UTF8.GetChars(sizeinfo));
            Debug.Print(message);
            return message;
        }

As you see, I wrote myScoket.Recieve twice because if i use it once, i get only the first byte of the message, and if i use it twice the message become complete, but it’s a problem because what if the message had only one byte? The code gets stuck…

Suggestion?


#2

Is the 1st byte the length info?
If yes I would really read only one byte at first

;
myScoket.Receive(sizeinfo, 0, 1, SocketFlags.None);

and then the remaining bytes like this


var buffer = new byte[sizeifo[0]];
int currentRead = 0;
while(currentRead < sizeifo[0])
{
   currentRead += myScoket.Receive(sizeinfo, currentRead, sizeifno[0} - currentRead, SocketFlags.None);[/
}

This ensures 2 things:
If the sizeifno is 0, no additional read is done
If the 2nd read does not contain all data, it is called again.

If the 1st byte is not the desired length, then it gets harder.
But somehow you need to find out if the message is complete


#3

@ Reinhard Ostermeier - The first byte isn’t the length info, for example I want to send a message: "ABCDEFG"
When I read the the message, I get “A” for the first time I call “receive” and at the next time I get “BCDEFG”.

I want to use receive once to get the whole "ABCDEFG"
What do u say?


#4

What triggers your readings? Socket is highly asynchronous, it may accept new data while still in .Receive() function! what does myScoket.Available property says before, between and after your reads?


#5

Normally if you send it from the other side with a single Send command, you should receive it as a single packet.
But receiving is an asynchronous process you never can be sure.
There for a good protocol design includes some kind of framing to know when a message is complete.
This could be the length info at the beginning, or if you have ASCII messages some special start and end characters (Look at an ASCII table, and you will find them).

Sending just plain messages without a defined beginning and end is (please apologize) “Stupid protocol design”.

Another method would be to make a minimum break between messages on the sender side, but in my opinion this is not a good deign as well, and it’s harder to read.

There are several methods/properties on a socket you can use to check if data is available for reading, like Poll() or Available.


#6

@ bioengproject -

[quote]I want to use receive once to get the whole "ABCDEFG"
What do u say?[/quote]

The only way to insure this is to use UDP instead of TCP. All received will be full messages, but this would be at expense of potential lost packets.

TCP is a stream protocol. There is no guarantee about how many bytes will be read with one read. That’s just the way it is…


#7

@ Reinhard Ostermeier - Can I assume that when I call mySocket.receive, I will get one byte ?? if the message’s length is 10 bytes? I will get just “1” as the size of the message.


#8

One of the parameters of read is the number of bytes you want to get. It will block until at least 1 byte is available.
The return value of read tells you how many bytes you have got, and have been written into your buffer. This will never be more then you wanted. The remaining bytes stays in the driver until you read it.
In the case you want 1 byte, the return value is always 1 when it returns with one exception.
If the socket gets closed (from the other side or a different thread) it return 0.

The code I posted above uses these features of the read method in the while loop