views:

313

answers:

2

Hello,

I've been working with asynchronous sending in C# lately, and just a couple of days ago when i encountered that i needed to send multiple bits of data, i started wondering if the data sent are sent in order.

So my question is, when you send data asynchronously in c-sharp, does it send the data accordingly as it's sent?

Eg. I send an array of data holding 10 bytes, and right after i send it, i send an array holding 5 bytes, would this mean that the array holding 5 bytes would reach the remote client first (seeing as 5 bytes would most likely take less time to process than 10)

Thanks for the help in advanced. Sorry if i couldn't explain well enough.

EDIT:

Here's the code (C#):

    /// <summary>
    /// Sends the welcome screen to the character.
    /// </summary>
    /// <param name="character">The character requesting the welcome screen.</param>
    public void SendWelcomeScreen(Character character)
    {
        SendWindowPane(character, 549);
        SendInterface(character, 1, 549, 2, 378);
        SendInterface(character, 1, 549, 3, 15);
        SendString(character, "Welcome to " + GameEngine.World.Name + ".", 378, 115);
        // TODO: last ip
        SendString(character, "You are connected from: " + character.Session.Connection.IPAddress, 378, 116);
        SendString(character, "0", 378, 39);
        SendString(character, "0", 378, 96);
        SendString(character, "0 unread messages", 378, 37);
        SendString(character, GameEngine.World.Name + " staff will NEVER email you. We use the Message Centre on the website instead.", 378, 38);
        SendString(character, "0 days of member credit", 378, 94);
        SendString(character, "You have 0 days of member credit remaining. Please click here to extend your credit.", 378, 93);
        SendString(character, "You do not have a bank pin. Please visit a bank if you would like one.", 378, 62);
        SendString(character, "You have not yet set any recovery questions.", 378, 56);
        SendString(character, "Message of the Week", 15, 0);
        SendString(character, "Remember to keep your account secure: set a bank PIN, set recover questions and NEVER give away your password.", 15, 4);
    }

    /// <summary>
    /// Sends a window pane to the character's client.
    /// </summary>
    /// <param name="character">The character to send window pane to.</param>
    /// <param name="pane">The pane id.</param>
    public void SendWindowPane(Character character, short pane)
    {
        character.Session.SendPacket(
            new PacketBuilder(239)
            .AppendShort(pane)
            .AppendByteA(0));
    }

    /// <summary>
    /// Sends an interface to the character's client.
    /// </summary>
    /// <param name="character">The character to send interface to.</param>
    /// <param name="showId">The show ids.</param>
    /// <param name="windowId">The window id.</param>
    /// <param name="interfaceId">The interface id.</param>
    /// <param name="childId">The child id.</param>
    public void SendInterface(Character character, byte showId, short windowId, short interfaceId, short childId)
    {
        character.Session.SendPacket(
            new PacketBuilder(93)
            .AppendShort(childId)
            .AppendByteA(showId)
            .AppendShort(windowId)
            .AppendShort(interfaceId));
    }

    /// <summary>
    /// Sends a piece of text to the character's client.
    /// </summary>
    /// <param name="character">The character to send the text to.</param>
    /// <param name="text">The string to be displayed.</param>
    /// <param name="interfaceId">The interface id of which we place this text on.</param>
    /// <param name="childId">The child id of which we place this text on.</param>
    public void SendString(Character character, string text, short interfaceId, short childId)
    {
        int stringSize = text.Length + 5;
        character.Session.SendPacket(
            new PacketBuilder(179)
            .AppendByte((byte)(stringSize / 256))
            .AppendByte((byte)(stringSize % 256))
            .AppendString(text)
            .AppendShort(childId)
            .AppendShort(interfaceId));
    }
A: 

That doesn't depend on whether it is async or sync. It depends on channel below: if TCP, order is honored. In UDP is not guaranteed.

Ariel
+1  A: 

The data is guaranteed to be sent in the order posted to the socket. In other words the order in which you call NetworkStream.BeginWrite or Socket.BeginSend. Ultimately what matters is the order in which WSASend is called by the framework for you (or the equivalent socket write done by CLR, I'm not sure if they not use WSAIoctl or even FileWriteEx, since they all work). From MSDN:

The completion routines can be called in any order, not necessarily in the same order the overlapped operations are completed. However, the posted buffers are guaranteed to be sent in the same order they are specified.

If you are using I/O completion ports, be aware that the order of calls made to WSASend is also the order in which the buffers are populated. WSASend should not be called on the same socket simultaneously from different threads, because it can result in an unpredictable buffer order.

So the order is guaranteed both within the scatter/gather buffer order of a single WSASend call and across multiple WSASend calls. The multiple thread invoking WSASend issue is obvious, so I hope is not the case with your code.

However usually things get out of order in the application on the receive side if you post multiple buffers to the socket with WSARecv or Socket.BeginReceive or NetworkStream.BeginRead, it is very easy to find yourself processing them out of order. Make sure this is not the case for you.

Remus Rusanu
BTW obviosuly this is in reference to TCP, your example is not clear as it actually misses the important calls, like the actual SEND. With UDP, order is not only not guaranteed, is actually unlikely to occur.
Remus Rusanu
Please pay attention to Remus last paragraph about the receive end usually getting out of order. This is the important part to understand. One reason is that the more possible network routes between you and your destination means the higher likelihood any two packets end up taking a different route. Many other factors come into play though. I only call that one out by way of example.
Jim Leonardo
I'm also assuming you're sending data independently of one another. Some protocols will take care of this for you if you wrap your data correctly as mentioned in other answers.
Jim Leonardo
Thanks guys, really helpful. I didn't really know what to search for on google/bing so i came to ask for specific helpThanks again :)
AJ Ravindiran