|
>>3327 ken > そのあと再びget_domainサブルーチンを呼び出すところからが… > どうなるのでしょうか??(^^; http://x68000.startshop.co.jp/~68user/net/resolver-2.html#6 の例だと、 最初に get_domain が受け取った $data が (0x04)www2(0xC0)(0x13).... で、一回目の while ループが終了した時点で $data = "(0xC0)(0x13)...." @domains=('www2');★1 となっています。 二回目の while ループでは my $len = unpack('C', $data); で $len は 0xC0 になり、 if ( ( $len & 0xc0 ) == 0xc0 ){ が真なので my $offset = unpack('n', $data) ^ 0xc000; ⇒ $offset は 0x13 my $new_data = substr($org_data, $offset); ⇒ $new_data は、UDP データグラム全体 ($org_data) の 0x13バイト目 substr($data, 0, 2) = ''; ⇒ $data は "(0xC0)(0x13)...." から "...." となる (先頭 2バイトを削る) となります。$new_data には (0x09)startshop(0x02)co(0x02)jp(0x00) が入っています。 ここで my ($domain_part) = get_domain($new_data, $org_data);★2 push(@domains, $domain_part);★3 と get_domain を再帰呼び出しすると、 sub get_domain { my ($data, $org_data) = @_; の $data には (0x09)startshop(0x02)co(0x02)jp(0x00).... が入っています。再帰呼び出しされた get_domain が処理を終えるときには @domains = ('startshop', 'co', 'jp'); となっており、最終的に return 'startshop.co.jp'; とドメインの一部を返します。 で、再帰呼び出しした側の get_domain に処理が戻ると、以下のような 流れになります。 ★1 の @domains にはすでに www2 が入っている ★2 の $domain_part には、再帰呼び出しした get_domain から受け取った startshop.co.jp が入っている ★3 で @domains = ('www2', 'startshop.co.jp') となる > また、else文の中の1行はどういった意味を持っているのでしょうか? > ここでいう「カウンタ」という物もよくわからなくて…。 (0x03)www(0x02)jp(0x07)FreeBSD(0x03)org(0x00) の 3・2・7・3・0 がここでいうカウンタです。$len には その後に続くバイト長が入っており、 508: substr($data, 0, 1) = ''; はその $len の部分を削っています。 # 説明文で使用していない用語 (カウンタ) を、ソースで使ってはいけませんね。 |
|
先日質問させていただいた、tomtomです。 クライアントが受信待ちの状態の時に、サーバに ソケットをクローズされたら、クライアントは、 どうなるのでしょうか? 以前質問させていただいた時に、undefを受信してしまう という問題があったのですが、サーバ側で勝手にセッションを 終了してしまっていた可能性があるので、その辺が関係している かどうか疑問に思ったため、再度質問させていただきました。 |
|
あ〜っ、なるほど! わかりました!完璧にわかって疑問が紐解けましたよ〜! get_domainの再起呼び出し後はそういう処理だったんですね…。 カウンタの意味もわかりましたし(^^;)、もうばっちりです! 長々と本当にありがとうございましたm(_ _)m もしまた何かありましたら…よろしくお願いいたします(^^; |
|
こんにちは、今Perl で UDP 通信を行うスクリプトを作っているの ですが、少し分からないところがあるので質問させてください。 普通に UDP 通信は問題なく行えているのですが、送信元の IP アドレスが 拾えなくて悩んでおります。 recv 関数の戻り値で「送信元のアドレス」は拾えるのですが、送信元が 「どこへ宛てて送信したか?」が分からないのです。 IO::Socket::INET モジュールを使用していますが、peeraddr メソッドを 使っても何も返ってきません。 http://x68000.startshop.co.jp/~68user/net/udp-3.html に UDP で connect 出来ると書かれていますが、connect すれば送信先アドレスを 拾う事ができますでしょうか? ご存じの方、よろしくお願いいたします。 |
|
>>3329 tomtom > クライアントが受信待ちの状態の時に、サーバにソケットを > クローズされたら、クライアントは、どうなるのでしょうか? 単に相手がソケットをクローズしただけなら、recv は 0 を 返します。 もし A が listen → B が connect → A がソケットクローズ → B が send → B が recv なら、B は SIGPIPE を受けます。 >>3331 lopper > recv 関数の戻り値で「送信元のアドレス」は拾える > のですが、送信元が「どこへ宛てて送信したか?」が > 分からないのです。 ソケットが送信先を記憶していないからです。同じ相手に 連続して UDP データグラムを送信する場合、 socket(SOCKET, PF_INET, SOCK_DGRAM, 0); send(SOCKET, "hoge1", 0, $sock_addr); send(SOCKET, "hoge2", 0, $sock_addr); と、毎回 send の引数に宛先である $sock_addr を指定 しなければいけません。なぜなら、一度目の send を 実行した後、SOCKET は $sock_addr に送信したことを 覚えていないからです。 # ソケットの先のアドレスが確定していないので、相手側で # エラーがあって ICMP メッセージが返ってきても、カーネルは # どのソケットにエラーを伝えればよいかわからない。だから # 非 connect な UDP では相手側のエラーを拾えないわけです。 > connect すれば送信先アドレスを拾う事ができますでしょうか? できます。 socket(SOCKET, PF_INET, SOCK_DGRAM, 0); connect(SOCKET, $sock_addr); この処理で SOCKET は「宛先が $sock_addr であること」を 覚えます。よって、この後 send する場合は send(SOCKET, "hoge1", 0); と宛先を省略できるのです。 C で言うと、connect(2) することで、sendto(2) ではなく send(2) が使えるということです。 |
|
68user さん、お返事ありがとうございます。 socket => connect を行う事で send を呼ぶ時に IP アドレスを 指定しなくても良くなるわけですね。 逆に recv などで受信する時はどうなのでしょうか。 例えば 192.168.0.255 宛のブロードキャストメッセージを受信しても 受信側からはブロードキャストメッセージを受信したのか、ユニキャストを 受信したのか分かりません。 Java などで UDP を使う時は相手が送信した IP アドレスと相手の IP アドレス両方が分かるようですが、Perl では難しいのでしょうか? |
|
ちょっと前にこのページが移転するかもと言っていましたが、 継続して使わせていただけることになりました。 68user's page は Startshop さん http://www.startshop.co.jp/ 両毛インターネットさん http://www.takauji.or.jp/ Netboy さん のご厚意により、回線・マシンを無料で使用させていただいて おります。ここに改めて感謝の意を表したいと思います。 |
|
>>3333 lopper > 例えば 192.168.0.255 宛のブロードキャストメッセージを受信しても > 受信側からはブロードキャストメッセージを受信したのか、ユニキャストを > 受信したのか分かりません。 一般的な BSD ソケットの API を使う以上は判断できないと思っています。 > Java などで UDP を使う時は相手が送信した IP アドレスと相手の IP > アドレス両方が分かるようですが、Perl では難しいのでしょうか? Java なら受け取ったデータグラムがブロードキャスト宛かどうかを 判断できるのでしょうか。 もしそうなら、Java が BSD ソケット API を使用せずネットワーク 機能を自前で作っているとは考えづらいので、BSD ソケット API で 実現可能なのだろうと思います。 DatagramSocket や DatagramPacket を見る限りでは、Java であっても 無理ではないかと思いましたが、もし可能なのであれば Java で記述 したサンプルプログラムを見せていただけますでしょうか。 |
|
おお、それはすばらしいですね。 もし私が両毛地方とか県南・県央(一部重複してますが)に住むことに なったら、率先して両毛インターネットさんを選びたいという気持ち でいっぱいです。 |
|
お返事ありがとうございます。 確実に Java で宛て先アドレスを取得できるという確認はしていない のですが、以下の IP Messenger for Java の中では行っている ようです。 http://www1.ttv.ne.jp/~digitune/Java/IPMsg/ からソースコードをダウンロードして、その中にある IPMProxyEvent.java ファイルの中にある、getToIPMAddress で見ている見たいです。 P.S. 私は Java には詳しくはないので、確実かどうかわかりません。 |
|
>>3336 へにか > 率先して両毛インターネットさんを選びたいという気持ちでいっぱいです。 本当に一銭たりともお金を払っていないので申し訳ないことです。 機会があればぜひとも。 >>3337 lopper > IPMProxyEvent.java ファイルの中にある、getToIPMAddress で > 見ている見たいです。 ぱっと見、Java 版 IP Messenger 独自機能である proxy 機能の ソースのように見えます。README には「proxy 機能は TCP で実装 されている」とありましたので、多分違うのではないかと思います。 ちなみに 本家 IP Messenger は、受けたメッセージがブロード キャストだと、ログに「(多)」などと表示されます。 しかしこれは UDP のレイヤで判別しているのではなくて、IP Messenger のアプリで使用するコマンドの IPMSG_BROADCASTOPT が 立っているかどうかで判断しています。 |
|
lopper です。 お返事ありがとうございます。 ブロードキャストの件了解しました。なるほど Java版 ではプロキシに TCP を 使用しているので IP アドレスが拾えるのですね。わかりました。 色々とありがとうございました。自分なりに他の道を探してみます。 |
|
tomtomです。 68userさん、お返事ありがとうございます。 そうですか、、もし、undefを返すなら以前の 説明がつくと思ったのですが、どうやら見当違い のようですね。 また、色々考えてみる事にします。 原因が分かったら、また書き込みさせていただきます。 |
|
こんにちわ。以前質問させてもらった者です。 それで、また質問なのですが(笑 Perlカテゴリの中のProxy Serverのことで質問です。 SIGPIPEシグナルが飛んで来た時用 ということで、$SIG{PIPE}を作られていますが、 これはどこで使用されているのでしょうか? 作っとけば勝手にってことなのでしょうか? お忙しいかと思いますが、よろしくお願いします。 |