サンプルが perl5 専用なワケ

前へ << TCP/IP と OSI 参照モデル 関数一覧 >> 次へ

perl5 と perl4 の違い

この web で解説したサンプルの perl スクリプトは、 全て Socket モジュールを使っていますので、perl5 でないと動作しません。

なぜ、perl4 でも動くように書かなかったかを説明しておきます。perl5 で Socket モジュールを使って HTTP クライアントを書くと

use Socket;

$host = "www.host.com";
$path = "/~foo/index.html";

$port = getservbyname('http', 'tcp');

$iaddr = inet_aton($host);
socket(SOCKET, PF_INET, SOCK_STREAM, 0);
$sock_addr = sockaddr_in($port, $iaddr);

connect(SOCKET, $sock_addr);
select(SOCKET); $|=1; select(STDOUT);
print SOCKET "GET $path HTTP/1.0\r\n\r\n";

while (<SOCKET>){
  print $_;
}
となります。一方 perl4 ではモジュールという仕組みがないため、 上記の Bold 部分は
$iaddr = (gethostbyname($host))[4];
socket(SOCKET, 2, 1, 0);
$sock_addr = pack("S n a4 x8", 2, $port, $iaddr);
というふうに書かなくてはいけません (これは perl5 でも動きます)。問題は socket 関数
socket(SOCKET, PF_INET, SOCK_STREAM, 0); # perl5 の場合
socket(SOCKET, 2, 1, 0);                 # perl4 の場合
の、第3引数、`SOCK_STREAM' と `1' という違いです。

SOCK_STREAM という文字列は /usr/include/sys/socket.h の 中で値が決まっています。FreeBSD や Linux では

#define SOCK_STREAM     1
#define SOCK_DGRAM      2
となっているのですが、Solaris では
#define SOCK_STREAM     2
#define SOCK_DGRAM      1
と全く逆になっているのです。つまり、perl4 で
socket(SOCKET, 2, 1, 0);
とすると、FreeBSD では SOCK_STREAM (つまり TCP/IP) を意味するのですが、 Solaris だと SOCK_DGRAM (つまり UDP/IP) を意味するわけです。

HTTP は UDP でなく TCP を使いますので、

socket(SOCKET, 2, 1, 0);
と書くと、FreeBSD では動くが、Solaris では動かないということになってしまいます。 ですから、Socket モジュールを使った結果、perl5 専用のスクリプトになったのです。

また、この他に

  • マジックナンバは使うべきでない。
    socket(SOCKET, 2, 1, 0) より socket(SOCKET, PF_INET, SOCK_STREAM, 0) の方がわかりやすい。
  • perl4 は時代遅れである。今となっては perl5 を使うべき。
  • 便利なモジュール (IO::Socket や Net::POP3 など) が使えない。
という考えもあります。
前へ << TCP/IP と OSI 参照モデル 関数一覧 >> 次へ

ご意見・ご指摘は Twitter: @68user までお願いします。