Создайте несколько соединений TCP в C #, затем ждите данных - PullRequest
3 голосов
/ 03 марта 2010

В настоящее время я создаю службу Windows, которая будет создавать TCP-соединения с несколькими компьютерами (один сокет на всех машинах), а затем прослушивать «события» с этих машин. Я пытаюсь написать код для создания соединения, а затем создать поток, который прослушивает соединение, ожидающее пакеты от машины, затем декодирует поступающие пакеты и вызывает функцию в зависимости от полезной нагрузки пакета. *

Проблема в том, что я не совсем уверен, как это сделать в C #. У кого-нибудь есть полезные предложения или ссылки, которые могут помочь мне сделать это?

Заранее спасибо за любую помощь!

Ответы [ 4 ]

5 голосов
/ 03 марта 2010

В зависимости от того, сколько одновременных клиентов вы планируете поддерживать, архитектура потокового соединения, вероятно, очень быстро выйдет из строя. Причина в том, что каждый поток требует значительных ресурсов. По умолчанию каждый поток .NET получает 1 МБ стекового пространства, то есть 1 МБ на соединение плюс любые издержки.

Вместо этого при поддержке нескольких подключенных клиентов обычно вы будете использовать асинхронные методы ( см. Также ), которые очень эффективны, поскольку Windows будет использовать «порты завершения», которые в основном освобождают поток, чтобы делать другие вещи, ожидая завершения какого-либо события.

Для этого вы должны рассмотреть такие методы, как BeginAccept, BeginReceive, BeginSend и т. Д.

Более простой подход, который также позволяет избежать блокирования вызовов и избежать нескольких потоков, состоит в использовании метода Socket.Select в цикле. Это позволяет одному потоку обслуживать несколько сокетов. Поток может только физически читать или записывать в один сокет одновременно, но идея в том, что вы проверяете состояние нескольких сокетов, которые могут содержать или не содержать данные для чтения.

В любом случае, подход «поток-на-соединение» поначалу намного проще, но он имеет значительные проблемы с масштабируемостью. Я бы посоветовал сделать это сначала с синхронными методами, такими как Accept, Receive, Send и т. Д. Затем, позже, рефакторинг вашего кода для использования асинхронных методов, чтобы вы не исчерпали память сервера.

2 голосов
/ 03 марта 2010

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

Чтобы создать соединение, вы можете сделать:

Socket sock = Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(new IPEndPoint(address, port));

Таким же образом вы можете создавать несколько соединений и сохранять там ссылки в списке словаря (по вашему выбору).

Для асинхронного получения данных в сокете вы можете сделать:

sock.BeginReceive(buffer, 0, buffer.len, SocketFlags.None, new AsyncCallback(OnDataReceived), null);

Метод OnDataReceived будет вызван после завершения операции приема.

В OnDataReceived метод, который вы должны сделать:

void OnDataReceived(IAsyncResult result)
{
   int dataReceived = sock.EndReceive(result);
   //Make sure that dataReceived is equal to amount of data you wanted to receive. If it is
   //less then the data you wanted, you can do synchronous receive to read remaining data.

  //When all of the data is recieved, call BeginReceive again to receive more data


  //... Do your decoding and call the method ...//
}

Надеюсь, это поможет вам.

0 голосов
/ 03 марта 2010

Я не знаю, возможно ли это в вашей ситуации, но задумывались ли вы об использовании службы WCF, которая вызывается несколькими компьютерами? Вы можете разместить это в пользовательской службе Windows или IIS. Он будет потреблять очень мало ресурсов при ожидании событий, и его будет гораздо проще кодировать, чем все эти низкоуровневые страшные сокеты. Это автоматически асинхронно. Вы получаете приятные сообщения в свой сервис, а не пакет, который вам нужен для десериализации и / или анализа. Вы можете использовать любое количество протоколов, таких как REST или двоичный.

Вам, конечно, нужно будет создать процесс на другом конце, который отправляет сообщения.

Просто мысль ...

Приветствия

0 голосов
/ 03 марта 2010

Есть один поток, который запускает accept () для получения новых соединений. Для каждого нового соединения, которое вы получаете, порождайте рабочий поток, используя пул потоков.

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