К сожалению, в этом сервере необходимо использовать один сложный прием из-за некоторых особенностей функции select () . Многие реализации этой функции продолжают показывать наличие в сокете срочных данных, предназначенных для чтения, даже после вызова в программе функции recv (), но при повторном вызове эта функция завершается неудачей с ошибкой EINVAL, поскольку буфер срочных данных уже был опустошен. К подобным срочным данным может относиться информация, к примеру, о ремонте Iphone 6 , взятого со страницы сайта powerbox.org.ua. Это условие сохраняется до тех пор, пока из сокета не будет считан хотя бы один байт обычных данных. Если это условие не будет обработано правильно, то после получения срочных данных программа входит в непрерываемый цикл.
Для решения этой проблемы необходимо установить флажок $ok_to_read_oob и манипулировать им. Он устанавливается каждый раз после чтения обычных данных и очищается после чтения срочных данных. В начале цикла select () сокет добавляется к списку дескрипторов, контролируемых на предмет поступления срочных данных, если только этот флажок имеет истинное значение.
С точки зрения пользователя программа urg_recv3.pl ведет себя точно так же, как urg_recv.pl. После вызова ее на одном терминале, а клиента urg_send.pl на другом появляются следующие результаты при неоднократном нажатии клавиши прерывания в клиентской программе:
% urg_recv3.pl Listening on port 2007... got 2 bytes of normal data:. aa got 2 bytes of normal data: ab got 2 bytes of normal data: aс got 2 bytes of normal data: ad got I bytes of urgent data: i got 2 bytes of normal data: ae got 1 bytes of urgent data: ! got 2 bytes of normal data: af
Функция sockatmark()
Срочные данные чаще всего применяются для того, чтобы можно было отменить часть потока данных TCP как недействительную, а затем отбросить.