2012/12/24

Bad arg length for Socket::pack_sockaddr_in - tcp socket communication by Perl

http://www.perlmonks.org/?node_id=642313

Perl を久々に触っていて、TCP 通信のコードを書こうと思った。ただ、自分がHACKしようと思っているソフトウェアはモダンなライブラリを使っておらず、低レベルなAPIを使っていたのでそれに合わせることにした。

そこで書いたのが以下のコードである。

#!/usr/bin/perl -w
use strict;
use warnings;
use IO::Socket;
use Data::Dumper;
my $socket = IO::Socket::INET->new(
Proto => 'tcp',
Type => SOCK_STREAM
) || die "creating socket: $!";
my $port = 80;
my $remote_addr = "www.google.com";
$remote_addr = pack_sockaddr_in( $port, $remote_addr );
connect($socket, $remote_addr);

このコードを実行すると「Bad arg length for Socket::pack_sockaddr_in, length is 14, should be 4 at invalid_tcp_code.pl line 15.」というエラーになる。なんでやねんと数十分悩み、よくよく pack_sockaddr_in関数のドキュメント を読んでみると、以下のようになっていた。第2引数には inet_aton 関数の戻り値を渡せとある。

Takes two arguments, a port number and an opaque string (as returned by inet_aton(), or a v-string).

要するにドキュメントはよく読みましょうね、、ってことで。。
動くコードの全体は以下の通りである。www.google.com に HTTP通信するコードだ。エラー処理は省略しているので注意。

#!/usr/bin/perl -w
use strict;
use warnings;
use IO::Socket;
use Data::Dumper;
my $socket = IO::Socket::INET->new(
Proto => 'tcp',
Type => SOCK_STREAM
) || die "creating socket: $!";
my $port = 80;
my $remote_addr = "www.google.com";
$remote_addr = pack_sockaddr_in( $port, inet_aton($remote_addr) );
connect($socket, $remote_addr);
my $query = "GET / HTTP/1.0\n\n";
send( $socket, $query, 0, $remote_addr );
my $buffer;
my $recv_remote_addr = recv( $socket, $buffer, 8080, 0 );
print Dumper $recv_remote_addr; # should be empty string.
print $buffer;
1;
view raw tcp_client.pl hosted with ❤ by GitHub

0 件のコメント: