Есть ли способ опрашивать сокет в C # только тогда, когда что-то доступно для чтения?
Вопрос
Мне интересно, есть ли способ опросить сокет в c #, когда выполняется только одно из условий (данные доступны для чтения), я знаю о сокет.Опрос метод, но это может возвращать значение true, если любое из 3 указанных условий возвращает значение true, как указано здесь: MSDN:Сокет.Опрос
Решение
Согласно документации MSDN, есть три причины, которые возвращают true для
Poll(microSeconds, SelectMode.SelectRead);
- если
Listen()
был вызван и ожидается соединение - Если данные доступны для чтения
- Если соединение было закрыто, сброшено или прекращено
Давайте посмотрим, сможем ли мы их различить:
- Вы всегда знаете, если
Listen()
вызывался раньше, поэтому вам не нужно учитывать эту причину, если вы этого не сделали. - Хорошо, ты пойдешь на это.
- Означает, что вы не можете оставаться в вызове Poll() и вам нужно выяснить, что же произошло на самом деле.Один из вариантов — проверить состояние сокета сразу после
Poll()
вернулся.
Заключение:
не нужно рассматривать
и 3.можно обработать, проверяя состояние сокета каждый раз, когда возвращается true.
Поэтому я бы выбрал (непроверенный):
if (s.Poll(microSeconds, SelectMode.SelectRead)))
{
if (!s.Connected)
// Something bad has happened, shut down
else
// There is data waiting to be read"
}
Другие советы
Вы можете использовать свойство Socket Available.Он возвращает объем данных, доступных для чтения.
Нашел что-то в классе NetworkStream.Свойство NetworkStream.DataAvailable возвращает true, если данные доступны для чтения.Возвращается объект сетевого потока, работающий с TcpListener и TcpClient.Это на один уровень абстракции выше, чем сокет.
Я не нашел способа перейти от Socket к NetworkStream.NetworkStream использует сокет и является потоковым представлением сокета.Но я не знаю, что там сетевой поток делает с сокетом.
Вы можете использовать системный вызов select() для базового дескриптора.
Вы можете использовать метод Select() вместо Poll().На самом деле при просмотре Socket.Poll с помощью ILSpy (инструмент-отражатель) внутренний код вызывает select в сокете.
Кроме того, вызов Poll() в узком цикле увеличит выделение памяти, поскольку при каждом вызове создается новый IntPtr[].Вызов Select() позволяет повторно использовать массивы вместо скрытого выделения новых.
значение true, если был вызван Listen и ожидается установление соединения;-или- значение true, если данные доступны для чтения;-или- значение true, если соединение было закрыто, сброшено или разорвано;в противном случае возвращает false.
Я понимаю, что вы хотите проверить, является ли второй вариант тем, который возвращает true?После проверки, возвращает ли опрос значение true, вы можете проверить, открыто ли соединение, это означает;не подключено, закрыто, сброшено или разорвано.
Если он открыт, то это второй вариант, возвращающий true.