2012-02-27 2 views
1

Если я правильно понял логику 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); 
    } 
} 

Или в anotherway, я могу использовать 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 методов работы медленный для меня и/или иногда сервер не может отправить данные в любому клиенту. Пакет может быть потерян.

Пример:

Client1 Полученных 103 пакетов

Client2 Полученными 107 пакетов

Client3 Получены 102 пакетов

Clientn Полученные 106 пакетов

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

Есть ли другие методы/логики/технологии для отправки одной информации более чем одному клиенту или что-то не так в моих примерах?

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

ответ

1

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

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

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

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

+0

Вы имеете в виду что-то вроде: Задача .Factory.FromAsync ( stream.BeginSend, stream.EndSend, buffer, 0, buffer.Length, client); я устанавливаю bool для проверки, если его жалоба – Racooon

+0

Да, и нет. Ваш вызов сокета FromAsync выглядит хорошо. Но не используйте отдельный bool, задача имеет свойство IsCompleted. Но на самом деле вам все равно, если это будет завершено или нет, так как просто планировать новые задачи для запуска, как только они будут завершены, используя метод 'ContinueWith'. Основная задача будет выполнять все проверки и планирование для вас. – Tyson

+0

Спасибо, Тайсон, я тестирую его сейчас. – Racooon

Смежные вопросы