Как распространить tcplistener входящие соединения по потокам в.NET?

15
задан Vertexwahn 4 March 2016 в 15:53
поделиться

5 ответов

Код, который я использовал, похож на это:

class Server
{
  private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);

  public void Start()
  {
    TcpListener listener = new TcpListener(IPAddress.Any, 5555);
    listener.Start();

    while(true)
    {
      IAsyncResult result =  listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
      connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event
      connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request)
    }
  }


  private void HandleAsyncConnection(IAsyncResult result)
  {
    TcpListener listener = (TcpListener)result.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(result);
    connectionWaitHandle.Set(); //Inform the main thread this connection is now handled

    //... Use your TcpClient here

    client.Close();
  }
}
14
ответ дан 1 December 2019 в 03:44
поделиться

Я полагаю, что Вы делаете это таким же образом как любую другую асинхронную операцию в.NET: Вы называете версию BeginXxx метода, в этом случае BeginAcceptSocket. Ваш обратный вызов выполнится на пуле потоков.

Объединенные потоки обычно масштабируются намного лучше, чем для каждого подключения потоком: после того как Вы преобладаете над несколькими десятками соединений, системных работ намного тяжелее в переключении между потоками, чем при получении фактической сделанной работы. Кроме того, каждый поток имеет свой собственный стек, который обычно является 1 МБ в размере (хотя он зависит от флагов ссылки), который должен быть найден в виртуальном адресном пространстве на 2 ГБ (в 32-разрядных системах); на практике это ограничивает Вас меньше чем 1 000 потоков.

я не уверен, использует ли пул потоков.NET в настоящее время его, но Windows имеет объект ядра, названный Портом Завершения ввода-вывода, который помогает в масштабируемом вводе-выводе. Можно связать потоки с этим объектом, и запросы ввода-вывода (включая принятие входящих соединений) могут быть связаны с ним. Когда ввод-вывод завершается (например, соединение прибывает), Windows выпустит поток ожидания, но только если количество в настоящее время выполнимых потоков (не заблокированный по некоторой другой причине) является меньше, чем настроенный предел масштабируемости для порта завершения. Обычно Вы установили это на маленькое несколько из количества ядер.

3
ответ дан 1 December 2019 в 03:44
поделиться

Я хотел бы предложить другой подход: Мое предложение использует только два потока. * один поток проверяет на входящие соединения. *, Когда новое соединение открылось, эта информация записана в структуру совместно используемых данных, которая содержит все текущие открытые соединения. * 2-й поток перечисляет ту структуру данных, и для каждого открытого соединения получают отправленные данные и отправляют ответы.

Это решение более масштабируемое мудрый потоком, и, если реализовано currectly должен иметь лучшую производительность, затем открывающую новый поток на открытое соединение.

2
ответ дан 1 December 2019 в 03:44
поделиться

В Поваренной книге O'Reilly C# 3.0 существует яркий пример. Можно загрузить сопроводительный источник от http://examples.oreilly.com/9780596516109/CSharp3_0CookbookCodeRTM.zip

1
ответ дан 1 December 2019 в 03:44
поделиться

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

Извините, не имеют образца.

0
ответ дан 1 December 2019 в 03:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: