473,378 Members | 1,382 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Buffering TCPIP data

I have a TCPIP socket providing data to my app.
My app works on messages (not textual) with a predefined footer (eg 0x01
followed by 0x02)

How should i go about buffering this and retrieving the complete messages ?

Current approach:
I have a byte array of eg 1MB to hold data until full messages are assembled
when socket is readable, i read all data into the buffer starting at the pos
after the last byte of data that was put into it (maintained through an
integer var LastPos).
A separate thread would scan the array when new data is added. If it finds
the footer 0x01,0x02 then it will take all data before this and copy it out
into a new array and publish this through an event argument as a
MessageRecieved event.
IMPORTANTLY it will then take all data after the 0x02 char and move it to
the front of the buffer.

Is this the best approach ?
Should i be using a Queue of type byte ?
Thoughts much appreciated

Thanks.
S.

Jun 27 '08 #1
9 1765
On Jun 6, 3:06 pm, ShaunO <Sha...@discussions.microsoft.comwrote:
I have a TCPIP socket providing data to my app.
My app works on messages (not textual) with a predefined footer (eg 0x01
followed by 0x02)

How should i go about buffering this and retrieving the complete messages ?

Current approach:
I have a byte array of eg 1MB to hold data until full messages are assembled
when socket is readable, i read all data into the buffer starting at the pos
after the last byte of data that was put into it (maintained through an
integer var LastPos).
A separate thread would scan the array when new data is added. If it finds
the footer 0x01,0x02 then it will take all data before this and copy it out
into a new array and publish this through an event argument as a
MessageRecieved event.
IMPORTANTLY it will then take all data after the 0x02 char and move it to
the front of the buffer.

Is this the best approach ?
Should i be using a Queue of type byte ?
Thoughts much appreciated
It sounds like you really want to create a circular buffer - although
then you *do* need to know the maximum size you'll ever run into, or
cope with the complexity of recreating the buffer as and when you need
to.

Your current solution sounds okay though. A Queue<bytewould work,
but extracting a whole range out as an array may be painful (I haven't
checked the API). It'll still have to do copying, anyway.

Jon
Jun 27 '08 #2
t'was my fault for mentioning Queue<T(in the lack the full context);
although reasonable for many producer/consumer scenarios, in this case
probably not ;-p

Marc
Jun 27 '08 #3
The messages could be any size but never likely to go above 128 bytes.
It would be very helpful if you could outline the benefits of a circular
buffer over the byte array that i outlined so that i can evaluate if i need
to re-implement.
Thanks,
Shhaun
"Jon Skeet [C# MVP]" wrote:
On Jun 6, 3:06 pm, ShaunO <Sha...@discussions.microsoft.comwrote:
I have a TCPIP socket providing data to my app.
My app works on messages (not textual) with a predefined footer (eg 0x01
followed by 0x02)

How should i go about buffering this and retrieving the complete messages ?

Current approach:
I have a byte array of eg 1MB to hold data until full messages are assembled
when socket is readable, i read all data into the buffer starting at the pos
after the last byte of data that was put into it (maintained through an
integer var LastPos).
A separate thread would scan the array when new data is added. If it finds
the footer 0x01,0x02 then it will take all data before this and copy it out
into a new array and publish this through an event argument as a
MessageRecieved event.
IMPORTANTLY it will then take all data after the 0x02 char and move it to
the front of the buffer.

Is this the best approach ?
Should i be using a Queue of type byte ?
Thoughts much appreciated

It sounds like you really want to create a circular buffer - although
then you *do* need to know the maximum size you'll ever run into, or
cope with the complexity of recreating the buffer as and when you need
to.

Your current solution sounds okay though. A Queue<bytewould work,
but extracting a whole range out as an array may be painful (I haven't
checked the API). It'll still have to do copying, anyway.

Jon
Jun 27 '08 #4
On Jun 6, 3:41 pm, ShaunO <Sha...@discussions.microsoft.comwrote:
The messages could be any size but never likely to go above 128 bytes.
It would be very helpful if you could outline the benefits of a circular
buffer over the byte array that i outlined so that i can evaluate if i need
to re-implement.
You'd implement the circular buffer with an underlying byte array - it
means that when you've copied the data out for the message, you can
just update the logical "next message start" to the end of the
previous one, with no extra copying involved - i.e. you don't copy the
data you've already received from the next message.

Jon
Jun 27 '08 #5
Just an idea - If you know that your message always ends in 0x01,0x02 why
not build each message on the fly?

Allocate a new block.
When you get something in from the socket, copy it byte by byte into the
block, checking for the footer.
When you find your footer :
1) Fire an event with the now-complete message
2) Allocate a new block and start copying into that.

I guess copying byte by byte when you get the TCP data in seems tedious -
but you have to check the data anyway so you know when your message is
finished.

Personally, I wouldn't go for a separate thread scanning the same buffer my
TCP socket was writing into.
If you use an event I don't think you need to worry about thread synching at
all since the message in the event is in a block your TCP thread has
finished with.

Just don't take too long in the event handler - now here's somewhere where
you might use a synchronized queue. So your handler just pushes the block on
the queue and then returns to your TCP code to finish handling the TCP
event.

Another worker thread can be looking at your queue and pulling messages off
and handling them while your TCP code isn't doing anything.

HTH,

Adam.
=========

"ShaunO" <Sh****@discussions.microsoft.comwrote in message
news:CE**********************************@microsof t.com...
>I have a TCPIP socket providing data to my app.
My app works on messages (not textual) with a predefined footer (eg 0x01
followed by 0x02)

How should i go about buffering this and retrieving the complete messages
?

Current approach:
I have a byte array of eg 1MB to hold data until full messages are
assembled
when socket is readable, i read all data into the buffer starting at the
pos
after the last byte of data that was put into it (maintained through an
integer var LastPos).
A separate thread would scan the array when new data is added. If it finds
the footer 0x01,0x02 then it will take all data before this and copy it
out
into a new array and publish this through an event argument as a
MessageRecieved event.
IMPORTANTLY it will then take all data after the 0x02 char and move it to
the front of the buffer.

Is this the best approach ?
Should i be using a Queue of type byte ?
Thoughts much appreciated

Thanks.
S.

Jun 27 '08 #6
(final question)
How does this handle the wrapping around - is there native support for doing
this somehow or would i need to check the pos left in buffer and break into
two parts putting one bit a the end of the buffer and the remainder at the
start ?
Thanks,
Shaun

"Jon Skeet [C# MVP]" wrote:
On Jun 6, 3:41 pm, ShaunO <Sha...@discussions.microsoft.comwrote:
The messages could be any size but never likely to go above 128 bytes.
It would be very helpful if you could outline the benefits of a circular
buffer over the byte array that i outlined so that i can evaluate if i need
to re-implement.

You'd implement the circular buffer with an underlying byte array - it
means that when you've copied the data out for the message, you can
just update the logical "next message start" to the end of the
previous one, with no extra copying involved - i.e. you don't copy the
data you've already received from the next message.

Jon
Jun 27 '08 #7
On Jun 6, 4:45 pm, ShaunO <Sha...@discussions.microsoft.comwrote:
(final question)
How does this handle the wrapping around - is there native support for doing
this somehow or would i need to check the pos left in buffer and break into
two parts putting one bit a the end of the buffer and the remainder at the
start ?
The latter - that's exactly why it would be a case of writing a
circular buffer instead of using an existing one :)

(There may well be existing third party implementations around already
- but your case is somewhat specialised as you'll want good support
for dealing with whole arrays of bytes rather than one byte at a
time.)

Jon
Jun 27 '08 #8
On Fri, 06 Jun 2008 08:45:01 -0700, ShaunO
<Sh****@discussions.microsoft.comwrote:
(final question)
How does this handle the wrapping around - is there native support for
doing
this somehow or would i need to check the pos left in buffer and break
into
two parts putting one bit a the end of the buffer and the remainder at
the
start ?
There is no built-in support for a circular buffer, AFAIK. You'd have to
implement the wrap-around logic yourself. Not _too_ hard, but can be a
little tricky.

That said, if you really need high-performance, it's probably the way to
go. Shifting all your data is potentially expensive, especially for a 1MB
buffer (alternatively, if your individual messages are relatively small,
are you sure you really need such a large buffer?).

Of course, if you don't need high-performance, you may want to consider
using much simpler techniques. For example, use smaller buffers for the
individual network i/o operations (anywhere from 1K up to 8K or so
depending on your usage), and then write the results into a MemoryStream
that represents each individual message. When you reach the terminator,
handle the current message by converting to bytes
(MemoryStream.ToArray()), passing to whatever code will actually process
it, and then start a new MemoryStream with the remaining bytes in your i/o
buffer.

That approach is likely to be much simpler than a circular buffer or
similar technique. If the performance is sufficient for your needs, IMHO
it's a much better way to go.

Pete
Jun 27 '08 #9
Thanks!

"Peter Duniho" wrote:
On Fri, 06 Jun 2008 08:45:01 -0700, ShaunO
<Sh****@discussions.microsoft.comwrote:
(final question)
How does this handle the wrapping around - is there native support for
doing
this somehow or would i need to check the pos left in buffer and break
into
two parts putting one bit a the end of the buffer and the remainder at
the
start ?

There is no built-in support for a circular buffer, AFAIK. You'd have to
implement the wrap-around logic yourself. Not _too_ hard, but can be a
little tricky.

That said, if you really need high-performance, it's probably the way to
go. Shifting all your data is potentially expensive, especially for a 1MB
buffer (alternatively, if your individual messages are relatively small,
are you sure you really need such a large buffer?).

Of course, if you don't need high-performance, you may want to consider
using much simpler techniques. For example, use smaller buffers for the
individual network i/o operations (anywhere from 1K up to 8K or so
depending on your usage), and then write the results into a MemoryStream
that represents each individual message. When you reach the terminator,
handle the current message by converting to bytes
(MemoryStream.ToArray()), passing to whatever code will actually process
it, and then start a new MemoryStream with the remaining bytes in your i/o
buffer.

That approach is likely to be much simpler than a circular buffer or
similar technique. If the performance is sufficient for your needs, IMHO
it's a much better way to go.

Pete
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: MPowell | last post by:
Gents/Ladies, I'm doing (at least plan on ) lots of Reads and Writes across a communication channel. I'm told that for the 'receive side' it'd be prudent to implement a double buffering scheme to...
0
by: Stuart Norris | last post by:
Dear Group, I am having a problem setting SocketOptionName.SendTimeout on a client TCPIP application using the sockets in .NET. From the on-line help it is possible to set a...
3
by: TulasiKumar | last post by:
hi all, My requirment is i want to listen one perticular TCPIP port for one IPAddress,Wheneverver the data in coming to this port that data i will be save one text file..For...
1
by: coolsti | last post by:
I am having a curious problem with Vista working on a Lenovo thinkpad. To test and demonstrate this problem, I have a PHP script that does not terminate. It enters an infinite loop where it...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.