views:

1232

answers:

2

i am new to programming and i am confused about asynchronous socket programming.

for example lets say i have 2 BeginSend, one right after another.

the first sends a million chars and the secnd sends only 64 chars.

due to the asynchronous nature won't the second BeginSend complete before the first one?

if so how can i tell the recieved data at EndRecieve, belongs to which message?

thanks for your time.

+1  A: 

The BeginSend method includes a parameter AsyncCallback callback. If you use two different callbacks, you can see which one completed first.

But if you are trying to send both messages on the same connection, you will have problems. You should wait until the first message is completely sent before sending the second.

Mark Byers
yes im sending both messages to the same address/port.
iEisenhower
I think the sending will probably work, but I suspect that the messages will become interleaved and unparseable.
Mark Byers
that the issue. how do i avoid that? it can be done because applications like mirc deal with these kind of issues all the time. i would like to know how can i implement it?
iEisenhower
waiting until first message is completely sent? i should have code in EndSend to check for completion of the first message?
iEisenhower
Yes. You don't need "code in EndSend to check for completion of the first message". When you get the callback, it means the Send has completed.
Mark Byers
are you sure about this behaviour when two BeginSend functions are called? If there is only one socket, I'd think that there would be a mutual exclusion on the socket. I actually think that an exception would be thrown if you call two BeginSend's together.
Fuzz
thanks Fuzz, you have mentioned a good point. im not sure of this behaviour. i am just trying to clear up doubt before coding.
iEisenhower
Mark: what i mean is setting a flag in BeginSend that message is begin sent. and in EndSend i modify it to state message has been sent. and then if any messages that have queued up, send them next.
iEisenhower
@Fuzz: you might be right, the best way to determine this is to try it. @ikurtz: you can start the next BeginSend in the body of your asynchronous callback function. You don't need a separate flag - you can just check if the queue is empty or not.
Mark Byers
"Your callback method should invoke the EndSend method. When your application calls BeginSend, the system will use a separate thread to execute the specified callback method, and will block on EndSend until the Socket sends the number of bytes requested or throws an exception." from MSDNYes Mark, I believe that is correct with respect to calling the next BeginSend from the call back
Fuzz
+3  A: 

You really shouldn't call two BeginSend's after one another. I think that you'll end up seeing exceptions thrown if this happens.

You have to call an EndSend before calling another BeginSend. This is typically done in side the callback function.

Check out the example Using an Asynchronous Client Socket at MSDN. In the callback the EndSend is called, and then a ManualResetEvent called "sendDone" is set. This is a form of inter-thread communication in which the callback is signaling to your main thread that the asynchronous send is completed. This then allows your program to cue up the next piece of data.

  • Call BeginSend from your main thread to send the first 1,000,000 bytes
  • Your main thread can check on a semaphore or something like the ManualResetEvent to trigger it to send the next 64 bytes. Your other option is to use a queue for the data to send
  • When the data has finished sending, the callback you passed in to the BeginSend will be called.
  • In this call back, you will call EndSend. Follow this then setting the ManualResetEvent, or what ever inter-thread trigger you wish to use.

The simplest option, which I recall doing once, is to call BeginSend for the next piece of data in the callback for the first piece of data being done.

e.g. int NumBytesSent; // member variable containing how many bytes you have sent so far string Message; // Message to send that is large

When you call BeginSend, pass in a chunk of say 100 bytes (pick a larger number for more efficient transfers, but not too large) to send and increment NumBytesSend by 100. Next, in your callback for the previous send being completed you can check if NumBytesSent < Message.Length, and if it is then send the next chunk of the Message.

This is how you would send a file you send a bunch of bytes at once, and just keep sending chunks of the file until it is all sent.

I highly recommend making a simple client/server to do something like sending a complete file over a connection. Also review the MSDN documents and the many other examples out and about in the web.

Getting a good grip on this will help you with lots of other C# topics as working asynchronously (or using delegates/callbacks) is very common for .NET

Fuzz
+1 for the suggestion to build something simple first.
Mark Byers
thanks Mark, thats always the way I build my network code.I've done this stuff MANY MANY times, but always start with a generic simple start point and work up from there.
Fuzz