my $server_message = do { local $/; <$SOCK> }
в клиентском скрипте пахнет смешно для меня. Устанавливая $/
в undef
, вы просите оператор <$SOCK>
прочитать все входные данные из дескриптора $SOCK
до конца файла. В этом контексте конец файла означает, что другой конец сокета закрыл соединение.
Сервер доставляет сообщение, как вы можете видеть, если вы измените строку выше на что-то вроде
print "Received message: ";
print while $_ = getc($SOCK);
(это также будет зависать на 5 секунд, когда входной поток исчерпан, но он будет по крайней мере отображать каждый символ на входе за это время).
Это «особенность», что один конец соединения через сокет TCP никогда не может узнать, действительно ли другой конец соединения еще жив. Сетевые программисты прибегают к другим соглашениям - кодирование длины сообщения в начале каждого сообщения, завершение каждого сообщения специальным токеном, реализация тактовых импульсов - для определения того, сколько входных данных можно безопасно прочитать из сокета (вы также можете посмотреть в версию с 4 аргументами select
)
Для этой проблемы одной из возможностей является применение соглашения о том, что все сообщения с сервера должны заканчиваться символом новой строки. Измените сценарий сервера, чтобы сказать
print $CLIENT $server_message, "\n";
и измените клиентский скрипт на
my $server_message = do { local $/="\n"; <$SOCK> }; # if you're paranoid about $/ setting
my $server_message = <$SOCK>; # if you're not
и вы получите результаты, более близкие к ожидаемым.