views:

74

answers:

2

C# socket server, which has roughly 200 - 500 active connections, each one constantly sending messages to our server.

About 70% of the time the messages are handled fine (in the correct order etc), however in the other 30% of cases we have jumbled up messages and things get screwed up. We should note that some clients send data in unicode and others in ASCII, so that's handled as well.

Messages sent to the server are a variable length string which end in a char3, it's the char3 that we break on, other than that we keep receiving data.

Could anyone shed any light on our ProcessReceive code and see what could possibly be causing us issues and how we can solve this small issue (here's hoping it's a small issue!)

Code below:

A: 

Firstly, I'm sure you know, but it's always worth repeating; TCP is a stream of bytes. It knows nothing of any application level "messages" that you may determine exist in that stream of bytes. All successful socket Recv calls, whether sync or async, can return any number of bytes between 1 and the size of the buffer supplied.

With that in mind you should really be dealing with your message framing (i.e. looking for your delimiter) before you do anything else. If you don't find a delimiter then simply reissue the read using the same SocketAsyncEventArgs, the same buffer and set the offset to where you currently are, this will read some more data into the buffer and you can take another look for the delimiter once the next read has completed... Ideally you'd keep track of where you last got to when searching for a delimiter in this buffer to reduce repeated scanning...

Right now you're not doing that and your use of e.Buffer[e.Offset] == 255 will fail if you get a message that arrives in pieces as you could be referring to any byte in the message if the message is split over multiple reads.

Len Holgate
The e.Buffer[e.Offset] = 255 is purely to dictate whether the client is running a unicode client or not, we're only interested in 255 as the very first message the client sends, then we set isUnicode in their state object and use that from then on. The delimiter is the first thing we're checking for (char3) after appending the content to states sb string. It's a bit odd as for 80% of the time it's working no problem, but when we're logging out our errors we're finding that a char3 was found but the string isn't complete from the start. That's the part which isn't making sense
Rob
Infact, it seems that a bunch of question marks are being pre-appended to most of the messages. Sounds like a unicode error but not sure where that's occuring either
Rob
For example: ??????????????????????????????????3mat88jonmatxxx2.19d99e0d54a6e18d00c105200e7175308bf6aa17e is a messed up message, should just be: 3mat88jonmatxxx2.19d99e0d54a6e18d00c105200e7175308bf6aa17e
Rob
It's not in any way odd that it works 80% of the time, in test situations this kind of problem will often work 100% of the time! The ???s are probably part of a previous message. Step one, deal with your message framing. Write some tests that call your code with various partial messages in the buffer, you just need code to call `ProcessReceieve()` and pass it a `SocketAsyncEventArgs` that you've filled with some data. Start with a single complete message, then write a test for a message that arrives in two pieces, then a buffer with two messages in, etc. Make sure you split unicode characters.
Len Holgate
Alternatively use a tool like this: http://www.codeproject.com/KB/IP/testingsocketservers.aspx to force your server to deal with reading messages in parts...
Len Holgate
Thanks Len, what you say makes sense. Thanks for the advice, it's much appreciated!
Rob
A: 

The problem I am seeing is that you are calling Encoding.Unicode.GetString() on a buffer you received in the current read from socket. However, the contents of that buffer might not be a valid unicode encoding of a string.

What you need to do is to buffer your entire stream, and then decode it as a string in one final operation, after you have received all the data.

feroze