Конференция "Сети" » Зависание над чтением сокета
 
  • It's not me (04.03.09 19:51) [0]
    Есть поток, который занимается постоянным чтением из сокета через RecvFrom. В любой момент может быть приказ о завершении работы (приложение завершается).

    Сигналом к тому, что пора завершаться является выставление у потока (в виде класса от TThread) свойства Terminated в true и дерганье определенного эвента, допустим WorkEvent;

    Не могу понять, как элегантно отслеживать данные ситуации.

    - если впрямую использовать RecvFrom, то при отсутствии данных поток зависнет в блокировке. Соответственно, так и будет висеть и никакими сигналами его не разбудить. Плохо.

    - есть такая функция select, ее можно использовать, но это только частично решает проблему. То есть, можно делать select на определенный TimeOut. После отвисания проверять свойство Terminated и опять select.
    Но тут проблема в том, чтобы выбрать оптимальный TimeOut. Чем он меньше - тем больше загрузка процессора на перепроверки, входы / выходы в синхронизацию и так далее. Чем больше TimeOut - тем медленнее средняя реакция потока на уведомления о завершении потока.

    - в идеале я вижу это как вызов: WaitForMultipleObject от двух объектов. С одной стороны, WorkEvent который дернется если потоку нужно завершаться, с другой стороны некий объект синхронизации, говорящий о том, что в сокет поступили данные. Вот наверняка есть же такой объект, который можно впихнуть в WaitXXX функции. Но найти его не могу )))

    Подскажите что делать, а скорее всего ответ просто в указании на соответствующий WinSock функции, которые позволяют создать такой объект.
  • Сергей М. © (04.03.09 20:04) [1]

    > соответствующий WinSock функции, которые позволяют создать
    > такой объект


    Ты не поверишь - это хорошо известная и всенароднолюбимая ф-ция WinAPI CreateEvent()

    И используется этот ивент в ф-ции WSAEventSelect


    > в идеале я вижу это как вызов: WaitForMultipleObject от
    > двух объектов


    Далеко не единственное и не всегда идеальное решение.

    Есть еще и MsgWaitForMultipleObjects. В комплексе с WSAEnumNetworkEvents позволяет преодолеть все мыслимые "неудобства".


    > если впрямую использовать RecvFrom, то при отсутствии данных
    > поток зависнет в блокировке


    Ничто не мешает закрыть хэндл гнезда из другого потока - блокирующая ф-ция тут же "отвиснет" с соответствующим ожидаемым кодом отказа.

    Это весьма распространенный и вполне коррекный способ прерывания блокирующей операции ввода-вывода.
  • Сергей М. © (04.03.09 20:09) [2]
    Собссно говоря, ф-ция такая имеется - WSACreateEvent.
    Но она не более чем раппер для CreateEvent.
  • Сергей М. © (04.03.09 20:16) [3]

    > можно делать select на определенный TimeOut


    В Indy именно так и реализовано. И никто не жалуется. А робкие жалобы перекрываются железным аргументом - кроссплатформенностью такого решения.
  • Slym © (05.03.09 04:46) [4]
    Закрыть сокет и Recvы отвалятся
    It's not me   (04.03.09 19:51)
    Сигналом к тому, что пора завершаться является выставление у потока (в виде класса от TThread) свойства Terminated в true

    и потом Socket.Close;
  • It's not me (05.03.09 11:53) [5]

    > Ничто не мешает закрыть хэндл гнезда из другого потока -
    >  блокирующая ф-ция тут же "отвиснет" с соответствующим ожидаемым
    > кодом отказа.
    >
    > Это весьма распространенный и вполне коррекный способ прерывания
    > блокирующей операции ввода-вывода

    корректный?! То есть, это вполне документировано? Ну тогда так и сделаю, спасибо большое!
  • Сергей М. © (05.03.09 12:45) [6]

    > It's not me   (05.03.09 11:53) [5]
    >
    >


    > так и сделаю


    Тогда возникунут проблемы с совместимостью решения с другими платформами.
    При неблок.режиме и select-мультиплексировании c таймаутом такавя проблема не возникнет.
  • It's not me (05.03.09 13:23) [7]

    > Тогда возникунут проблемы с совместимостью решения с другими
    > платформами

    с линуксом что ли? ))))
    Я даже не планирую делать кроссплатформенную систему. Там несовместимостей будет как грязи )))
  • Сергей М. © (05.03.09 13:28) [8]

    > даже не планирую делать кроссплатформенную систему


    Тогда есть ненулевой резон задействовать возможности асинхронного режима, характерные именно для WSP - семейство WSAxxx-ф-ций, в частности WSA[Async/Event]Select, о которых ты заикнулся в самом начале.
  • It's not me (05.03.09 13:56) [9]
    А нафига? Так закрытие сокета из другого потока, когда первичный поток висит на RecvFrom нормально или все таки не очень нормально?
  • Сергей М. © (05.03.09 14:24) [10]
    MS это не комментирует.

    Но судя по фактической успешности такого решения для Winsock 2 (никакие проблемы при этом не наблюдаются) оно имеет право на жизнь.
 
Конференция "Сети" » Зависание над чтением сокета
Есть новые Нет новых   [134435   +33][b:0][p:0]