(Асинхронный) Правильная отправка данных нескольким клиентам - PullRequest
1 голос
/ 27 февраля 2012

Если я правильно понял логику BeginSend:

private void sendToClient(Client client, String data)
{
    byte[] byteData = Encoding.UTF8.GetBytes(data); //It must be UTF8

    client.BeginSend(byteData, 0, byteData.Length, 0, 
                     new AsyncCallback(sendCallback), client);
}
private void sendCallback(IAsyncResult iar)
{
    Socket client = (Socket)iar.AsyncState;
    int bytesSent = client.EndSend(iar);
}

Я отправил данные одному клиенту правильно.

Но если я хочу отправить данные для большего количества клиентов:

/**
 * I am using dictionary, because I hold the clients with login-key
 */
private void SendToClients(Dictionary<string, Client> connectedClients, String data)
{ 
    foreach(Client client in connectedClients.Values)
    {
        sendToClient(client, data);
    }
}

Или по-другому, я могу использовать SocketAsyncEventArgs для отправки всех клиентов:

private void sendToClients(Dictionary<string, Client> connectedClients, String data)
{
    SocketAsyncEventArgs asyncEvent;
    byte[] byteData = Encoding.UTF8.GetBytes(data); //It must be UTF8

    lock (connectedClients)
    {
        foreach (Client client in connectedClients.Values)
        {
            try
            {
                asyncEvent = new SocketAsyncEventArgs();
                asyncEvent.SetBuffer(byteData, 0, byteData.Length);
                client.Socket.SendAsync(asyncEvent);
            }
            catch (Exception ex)
            {
                //ERROR.
            }
        }
    }
}

Но оба метода sendToClients работают медленно для меня и / или иногда сервер не может отправить данные клиенту любому . Пакет может быть потерян.

Пример:

Клиент1 получил 103 пакета

Client2 получил 107 пакетов

Client3 получил 102 пакета

Clientn получил 106 пакетов

Но в конце должно быть 111 пакетов.

Существуют ли другие методы / логики / технологии для отправки одних данных более чем одному клиенту или что-то неправильно использовалось в моих примерах?

Заранее спасибо.

1 Ответ

1 голос
/ 27 февраля 2012

Этот код выглядит нормально, но это зависит от кода вызова, инициирующего несколько вызовов отправки.Обратите внимание, что вы не можете безопасно вызывать BeginSend несколько раз, прежде чем завершится каждая предыдущая операция.Смотрите здесь: Async Socket Writes - Потенциал для операций отправки, чтобы быть перепутанным?(Сокеты .NET) .Это может объяснить количество полученных вами недетерминированных пакетов.Поэтому, если вы хотите использовать этот подход, вам, вероятно, следует использовать некоторый механизм, который предотвращает множественные вызовы BeginSend до завершения предыдущих.

Но в последнее время я использовал новый TPL и его Task.Factory.FromAsync метод преобразования старого стиля APM Begin / End X в Task<T>:

http://blogs.msdn.com/b/pfxteam/archive/2009/06/09/9716439.aspx

После того, как у вас есть объект Task, можно просто запланировать следующую отправку (без наложенияпредыдущий) с помощью метода Task.ContinueWith.

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