Есть ли способ опрашивать сокет в C # только тогда, когда что-то доступно для чтения?

StackOverflow https://stackoverflow.com/questions/1249643

  •  12-09-2019
  •  | 
  •  

Вопрос

Мне интересно, есть ли способ опросить сокет в c #, когда выполняется только одно из условий (данные доступны для чтения), я знаю о сокет.Опрос метод, но это может возвращать значение true, если любое из 3 указанных условий возвращает значение true, как указано здесь: MSDN:Сокет.Опрос

Это было полезно?

Решение

Согласно документации MSDN, есть три причины, которые возвращают true для

Poll(microSeconds, SelectMode.SelectRead);

  1. если Listen() был вызван и ожидается соединение
  2. Если данные доступны для чтения
  3. Если соединение было закрыто, сброшено или прекращено

Давайте посмотрим, сможем ли мы их различить:

  1. Вы всегда знаете, если Listen() вызывался раньше, поэтому вам не нужно учитывать эту причину, если вы этого не сделали.
  2. Хорошо, ты пойдешь на это.
  3. Означает, что вы не можете оставаться в вызове Poll() и вам нужно выяснить, что же произошло на самом деле.Один из вариантов — проверить состояние сокета сразу после Poll() вернулся.

Заключение:

  1. не нужно рассматривать

  2. и 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top