Проще всего это сделать, поместив код чтения строки из сокета в небольшой блок и локализовав переменную $/ (с помощью оператора local), чтобы ее текущее значение автоматически сохранялось при входе в блок и восстанавливалось при выходе. В самом блоке значение переменной $/ устанавливается равным crlf.
При получении условия конца файла EOF от пользователя или сервера выполняется выход из цикла путем вызова оператора last.
На первый взгляд этот несложный сценарий кажется работоспособным. Например, в следующем фрагменте показан сеанс связи с FTP-сервером. Сразу после подключения сервер выдает заголовок приглашения (код сообщения 220). Пользователь вводит команду USER протокола FTP, указывает имя “anonymous” и получает подтверждение. Затем пользователь задает пароль с помощью команды PASS и получает еще одно подтверждение. Кажется, что все идет гладко.
К сожалению, эта идиллия вскоре заканчивается. На следующем этапе предпринимается попытка выполнить команду HELP, которая должна вывести многострочную сводку команд FTP. Этого не происходит. Получена первая строка ожидаемого вывода, после чего сценарий останавливается, ожидая ввода следующей команды. Пользователь еще раз вводит команду HELP и получает вторую строку вывода первой команды HELP. После ввода команды QUIT он получает третью строку вывода команды HELP.
Очевидно, что синхронизация сценария нарушена. В том виде, какой он сейчас имеет, сценарий может справляться только с такой ситуацией, когда в ответ на строку, введенную пользователем, поступает одна строка, выведенная сервером. Не имея возможности обрабатывать многострочный вывод, этот сценарий не может справиться с ответом на команду HELP.