#!/usr/local/bin/perl -w # $Id: ftp-client.pl,v 1.2 2002/02/05 17:53:09 68user Exp $ use Socket; # Socketモジュールを使う $hostname = 'localhost'; $username = 'zxr400'; $password = ''; #---------- コマンドコネクションを作成 ----------------- # FTP プロトコルを使う $port = getservbyname('ftp', 'tcp'); # ホスト名を、IPアドレスの構造体に変換 $iaddr = inet_aton($hostname) or die "$hostnameは存在しないホストです。\n"; # ポート番号と IP アドレスをまとめて構造体に変換 $sock_addr = pack_sockaddr_in($port, $iaddr); # ソケット生成 socket(COMMAND, PF_INET, SOCK_STREAM, 0) or die "ソケットを生成できません。\n"; # 指定のホストの指定のポートに接続 connect(COMMAND, $sock_addr) or die "$hostname のポート $port に接続できません。\n"; # ファイルハンドル COMMAND をバッファリングしない select(COMMAND); $|=1; select(STDOUT); #---------- ユーザ認証 --------------------------------- print COMMAND "USER $username\r\n"; print COMMAND "PASS $password\r\n"; #---------- データ用コネクションを作成 ----------------- # データコネクション用のソケット生成・アドレス割り付け for ( $data_port=5000 ; $data_port<65536 ; $data_port++ ){ # ソケット生成 socket(DATA_WAITING, PF_INET, SOCK_STREAM, 0) or die "ソケットを生成できません。\n"; # ソケットオプション設定 setsockopt(DATA_WAITING, SOL_SOCKET, SO_REUSEADDR, 1) or die "setsockoptでエラーが発生しました。\n"; # ソケットにアドレス(=名前)を割り付ける if ( bind(DATA_WAITING, pack_sockaddr_in($data_port, INADDR_ANY)) ){ # 成功したら forループを抜ける last; } else { # 失敗したら次のポートのbindを試みる print "ポート$data_portのbindに失敗しました。\n"; # ポート65535まで試してもダメなら終了 if ( $data_port == 65535 ){ die "終了します。\n"; } } } # OSに、クライアントからの接続を受け入れるよう指示 listen(DATA_WAITING, SOMAXCONN) or die "listen: $!"; #---------- ローカルホストの IP アドレスを取得 --------------- $local_sock_addr = getsockname(COMMAND); ($local_port, $local_addr) = unpack_sockaddr_in($local_sock_addr); $local_ip = inet_ntoa($local_addr); # IPアドレス aaa.bbb.ccc.ddd を aaa,bbb,ccc,dddという形式に $local_ip =~ s/\./,/g; #---------- PORT・LIST コマンドを送信 ------------------------- # FTP サーバに、データコネクションの IP アドレスとポートの情報を渡す printf COMMAND "PORT $local_ip,%d,%d\r\n" ,$data_port/256,$data_port%256; # ファイル一覧を送るよう要求 print COMMAND "LIST\r\n"; #---------- データコネクションを使って、データ受信 ----------- # FTP サーバ側からの接続を待つ accept(DATA, DATA_WAITING); # 送られてくるデータの内容を表示 while (){ print $_; } #---------- 終了処理 ---------------------------------------- # データ用コネクションclose close(DATA); close(DATA_WAITING); # QUITを送ってセッション終了 print COMMAND "QUIT\r\n"; close(COMMAND);