Есть несколько способов проверить, ожидают ли сокеты данных. Один из них - просто проверить свойство Pending
каждого сокета и вызывать метод Receive только при наличии данных. Однако это не очень хорошо масштабируется, и я бы рекомендовал использовать его только в приложениях с одним подключением или около того.
Функция Socket.Select может принимать IList of Sockets и через короткий промежуток времени сократит этот список до тех сокетов, которые ожидают данных. После этого вы можете безопасно получать звонки на них без блокировки.
Другой способ, который является предпочтительным, заключается в использовании API асинхронного сокета. (Звоните на BeginReceive
или BeginRead
в NetworkStream). В этих случаях вызов не будет блокироваться, и вы можете продолжить выполнение кода после вызова. Вы передаете функцию в качестве аргумента, который должен выполняться при ожидании данных в сокете. Это обрабатывается в фоновом потоке в пуле потоков .NET, поэтому здесь возникают проблемы с параллелизмом, в отличие от двух предыдущих методов. Асинхронные операции выполняются на гораздо более низком уровне в ОС, используя прерывания, чтобы сообщить ЦПУ, когда данные ожидают в сети, вместо того, чтобы периодически запрашивать данные, как это делает Select.