views:

80

answers:

1

I'm writing a program that will have both a server side and a client side, and the client side will connect to a server hosted by the same program (but by another instance of it, and usually on another machine). So basically, I have control over both aspects of the protocol.

I am using BeginReceive() and BeginSend() on both sides to send and receive data. My question is if these two statements are true:

  1. Using a call to BeginReceive() will give me the entire data that was sent by a single call to BeginSend() on the other end when the callback function is called.

  2. Using a call to BeginSend() will send the entire data I pass it to the other end, and it will all be received by a single call to BeginReceive() on the other end.

The two are basically the same in fact.

If the answer is no, which I'm guessing is the case based on what I've read about sockets, what is the best way to handle commands? I'm writing a game that will have commands such as PUT X Y. I was thinking of appending a special character (# for example) to the end of each command, and each time I receive data, I append it to a buffer, then parse it only after I encounter a #.

+1  A: 

No, you can't expect BeginReceive to necessarily receive all of the data from one call to BeginSend. You can send a lot of data in one call to BeginSend, which could very well be split across several packets. You may receive each packet's data in a separate receive call.

The two main ways of splitting a stream into multiple chunks are:

  • Use a delimiter (as per your current suggestion). This has the benefit of not needing to know the size beforehand, but has the disadvantage of being relatively hard to parse, and potentially introducing requirements such as escaping the delimiter.
  • Prepend the size of each message before the message. The receiver can read the length first, and then know exactly how much data to expect.
Jon Skeet
That's what I thought. Just to make sure I know how to parse the data if I use a delimiter: the data from two separate `BeginSend` calls cannot be received by a single `BeginReceive` call, right? For example, if I do `BeginSend("A"), BeginSend("B")`, there is no way `BeginReceive` will return "AB", is there? So can I rely on having the delimiter as the last character in the receive buffer, and everything before it a single command at some point?
IVlad
Repeat after me; TCP is a stream of bytes. Your sends are not messages. Your receives can return anywhere from 1 byte to the size of the buffer that you give it. There are no 'messages'. TCP is a stream of bytes.
Len Holgate
@IVlad: Len is absolutely correct. Don't try to work around TCP being a stream of bytes - go with it. The data from two calls to BeginSend could *absolutely* be returned by one call to BeginReceive.
Jon Skeet