how to handle multiple-message-in-same data-buffer (asyncprogramming)

A

asharda

Hello,

I have written a sample async code (using callback/async).
I am now seeing a situation where-in if two messages are received at
the same-time, both of them show-up in the data-buffer.

Given that i am new to this, can you point to resources or suggest
ways to handle this scenario? (the program runs indefinitely, handling
messages as they come in).

Here is the statement that stores the incoming bytes into a string:

myCompleteMessage = String.Concat(myCompleteMessage,
Encoding.ASCII.GetString(m_DataBuffer, 0, bytesRead));

Note that m_DataBuffer is a byte-array //byte[] m_DataBuffer = new
byte[20000];

There is 'content-length' field in the data that i get, but not sure
how to go-about handling both (or multiple) messages.

Thanks for your time.
Regards,
RS
 
A

asharda

[...]
There is 'content-length' field in the data that i get, but not sure
how to go-about handling both (or multiple) messages.

What do you mean by "content-length" field? Does that reliably describe
the actual bytes that are sent? If so, then you'll want to get that
value, and then use it to determine how many bytes are to be included in
the current message. Use only that many bytes, and save the remaining
bytes to be used later.

Without more specific information from you (for example, what is actually
being sent), it's hard to offer any specific advice. The fundamental
issue is that you need to know how many bytes constitute a single message,
and process only those bytes when processing that single message.

Pete

In async programming model, if two messages are received exactly at
the same time by the server, how does it handle it? (is it on separate
threads?).

Yes, there is a content-length field that accurately describes the #
of bytes in the message (similar to a http-post that will have header-
fields consisting of content-length and other fields, and then body
consisting of the message).
I can write a program/method to check if there is more than 1 instance
of content-length and then filter/process accordingly. But isnt there
a more better way to handle scenarios where-in two messages are
received in the same buffer?

Thanks.
RS
 
A

asharda

It depends on what you mean. But generally, if it's _not_ on separate
threads, then the recipient (whether server or client) is by definition
_not_ receiving two messages exactly at the same time. A single thread
can only process a single thing in a given moment.

The other issue is that when using TCP there is no such thing as a
"message", except as your own application code defines it. The .NET
classes (Socket, TcpClient, whatever you're using) won't know anything
about a "message".

Your question is somewhat vague, because it's not clear what you mean by
"exactly at the same time". There are at least three different ways to
read the question.

If you're talking about receiving two messages that were sent on the same
connection by the same sender, then the only "same time" you could be
talking about is that they may be combined into a single chunk of data to
be received by your server. But in that case, by definition that single
chunk will be processed by a single thread.

If you're talking about receiving two messages that were sent over two
different connections (e.g. two different senders, or the same sender
using two different connections), then the messages will be separated
according to the connection. Two different threads could in fact be
processing completed i/o on two different connections, but in that case
there should be no confusion because each connection will have its own
context (you should be passing a per-connection data structure when you
post the receive by calling Socket.BeginReceive()).

I hesitate to even describe the third scenario, since I doubt it applies
to you, and it might only confuse the issue. But for completeness's sake,
I'm including it anyway (but don't worry if you don't "get" it)...

Finally, I don't think this is what you're talking about, but you could be
describing a situation where you've posted more than one receive on a
connection at a time. This is a common technique in high-performance IOCP
servers, but it's fairly advanced and not something most people do on
their first try. But for code that does this, since you've got two or
more asynchronous operations that have been started simultaneously, that
means you could have two or more asynchronous operations complete at the
same time.

So, you could have two different threads receiving data on the same socket
at the same time. But that data is not necessarily going to be grouped as
individual "messages" between the two threads. The only thing you're
guaranteed (as I wrote before) is that the bytes received will be in the
exact same order as they were when they were sent.

That order is defined, by the way, according to the order in which you
posted the asynchronous receives (e.g. you called Socket.BeginReceive()).
The i/o completion may be posted out of order, but the data is guaranteed
to be in the right order in your buffers. This means that before you
start processing a chunk of received data, you need to check to make sure
you've completed receives on all of the buffers that were posted before
the one you're operating on currently. If you haven't, then you need to
set aside the current buffer (in an ordered queue, for example) and wait
to process it until you've seen the completion for previous buffers.

Now, all of this only applies if you post more than one receive on a given
socket at a time. IOCP allows this, and thus .NET inherits it as well.
But if you only call BeginReceive() once and don't call it again until
you've called EndReceive(), then obviously you will never be notified for
the completion of i/o on that socket in more than one thread at a time.

Now as far the rest of your post goes...


If the "content-length" field describes the number of bytes for that
transmission, then you should just use that number of bytes to determine
where that message ends and the next one begins.

If it doesn't describe the number of bytes for that transmission, then
yes...you seem to be left with the option of using the "content-length"
field (assuming it's the very first thing in a transmission) as the
delimiter for the message. This assumes, of course, that the rest of the
data in a message will never contain the text "content-length". This is
definitely not the case for HTTP, which you have compared your own
situation to, so this might not work.

Once again, there is no way to say for sure what you need to do until you
describe more precisely what is actually being sent and how you're
expected to process it.

Pete

Pete, appreciate your patience and explanation.
I segregated the stream of data using the 'separator' criteria (there
is a way to find where the next 'message' starts) and it appears to
have taken care of this issue. The content-length though is part of
the incoming stream, but it wasn't in the beginning.

Of the 3 possible scenarios you described, possibly the first-one is
applicable in my instance.

Thanks Again.
RS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top