C # Асинхронная отправка - PullRequest
       23

C # Асинхронная отправка

0 голосов
/ 11 ноября 2009

Я работал с асинхронной отправкой в ​​C # в последнее время, и всего пару дней назад, когда я обнаружил, что мне нужно отправить несколько бит данных, я начал задаваться вопросом, отправляются ли отправленные данные по порядку.

Итак, мой вопрос: когда вы отправляете данные асинхронно в C #, отправляет ли он данные соответствующим образом по мере их отправки?

Например. Я отправляю массив данных, содержащий 10 байтов, и сразу после отправки отправляю массив, содержащий 5 байтов. Означает ли это, что массив, содержащий 5 байтов, сначала достигнет удаленного клиента (поскольку 5 байтов, скорее всего, потребуют меньше времени для обработки, чем 10)?

Вот код (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));
    }

Ответы [ 2 ]

1 голос
/ 11 ноября 2009

Данные гарантированно будут отправлены в порядке, размещенном в сокете. Другими словами, порядок, в котором вы вызываете NetworkStream.BeginWrite или Socket.BeginSend . В конечном счете, важен порядок, в котором WSASend вызывается для вас фреймворком (или эквивалентной записью сокетов, выполненной CLR, я не уверен, что они не используют WSAIoctl или даже FileWriteEx , так как все они работают). Из MSDN:

Процедуры завершения могут быть вызваны в любом порядке, не обязательно в тот же порядок перекрывающихся операций завершены. Тем не менее, опубликовано буферы гарантированно будут отправлены в в том же порядке они указаны .

Если вы используете порты завершения ввода / вывода, знать, что порядок звонков для WSASend также порядок, в котором буферы заполнены . WSASend не должен вызываться на то же розетка одновременно из разных потоки, потому что это может привести к непредсказуемый порядок буфера.

Таким образом, порядок гарантирован как в пределах буфера разброса / сбора одного вызова WSASend, так и при нескольких вызовах WSASend. Многопоточность, вызывающая проблему WSASend, очевидна, поэтому я надеюсь, что это не так с вашим кодом.

Однако обычно все выходит из строя в приложении на принимающей стороне, если вы отправляете несколько буферов в сокет с помощью WSARecv или Socket.BeginReceive или NetworkStream.BeginRead , очень легко найти себя, обрабатывая их не по порядку. Убедитесь, что это не так.

0 голосов
/ 11 ноября 2009

Это не зависит от того, является ли он асинхронным или синхронизированным. Это зависит от канала ниже: если TCP, заказ выполняется. В УДП это не гарантировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...