Как мне установить `SO_RCVTIMEO` для сокета в Perl? - PullRequest
1 голос
/ 27 ноября 2011

Если я попытаюсь так:

my $sock = IO::Socket::INET->new( … )                    or die "no socket for you";
defined $sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, 30)   or die "setsockopt: $!";

, тогда мой сценарий погибнет от "setsockopt: Неверный аргумент в [строка 2]".В модулях IO::Socket и perlfunc ничего не сказано, хотя perlfunc приводит пример с TCP_NODELAY, который выглядит так, как будто выше должно работать.

( быстрое примечание: I 'Мы ответили на мой собственный вопрос, как могли, но, конечно, приветствуем лучший ответ. Самым очевидным «лучшим» будет его переносимость, по крайней мере на компьютерах POSIX)

Ответы [ 2 ]

3 голосов
/ 27 ноября 2011

Используя strace в интерпретаторе Perl, выполняющем скрипт, становится ясно, что проблема в том, что Perl не упаковывает struct timeval (требуется SO_RCVTIMEO) для вас.Кроме того, не существует вспомогательных функций, которые могут сделать это за вас.Вместо этого вы должны сделать это самостоятельно.

Это оказывается проблематичным, поскольку struct timeval зависит от конкретной машины.Единая спецификация Unix определяет ее :

Заголовок должен определять временную структуру, которая должна включать как минимум следующие члены:

time_t         tv_sec        Seconds.
suseconds_t    tv_usec       Microseconds.

В нем также говорится, что time_t является целочисленным или вещественно-плавающим типом, а «suseconds_t должен быть целочисленным типом со знаком, способным хранить значения по крайней мере в диапазоне [-1, 1000000]» (см. sys / types.h).

Без доступа к структуре C это невозможно сделать переносимым.Но если мы примем glibc, у него будет более ограничительное определение, указывающее как long, и что они являются единственными двумя членами.Тем не менее, это ошибка документации .Так что не бери в голову.

Итак, лучшее, что я могу сделать, что, как я считаю, работает как на GNU / Linux IA-32, так и на GNU / Linux AMD64, это:

$sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, pack('l!l!', 30, 0))
    or die "setsockopt: $!";

The pack format l! означает использование нативной текущей машины long, о которой говорят документы glibc, и, по-видимому, она реализована, по крайней мере, для некоторых архитектур glibc (но не SPARC, согласно ошибке).

0 голосов
/ 27 ноября 2011

Работает ли $myiosockinet->timeout( 30 ); или $myiosockinet->timeout( 30 * 1000000 );?

Если это не так, этот модуль (IO::Socket::INET или Socket) нуждается в обновлении :), поскольку http://search.cpan.org/~flora/perl-5.14.2/pod/perlfaq8.pod#Where_do_I_get_the_include_files_to_do_ioctl%28%29_or_syscall%28%29%3F неудовлетворительно

...