[ruby-list:50369] Re: [質問] Ruby socket.send でUDP Packet が出ない? ネットワーク環境によるものか?
From:
Toshihiko Ichida <dogatana@...>
Date:
2016-08-03 12:50:30 UTC
List:
ruby-list #50369
市田です。
何点か気になる点があります。
1. 現象について
「ブロック」と表現されているのですが、該当スクリプトではタイムアウトを検
出するようになっているので、デバイスからの応答を受け取れない場合、
>> Couldn't find any UPnP devices.
と表示して終了することになり、ブロックしたままになることはないはずです。
設定したタイムアウト時間が経過してもこの表示が出ず、動作がブロックしてい
るのであれば、タイムアウト検知がうまく働かない状況で、少なくとも私のとこ
ろとは別の現象が発生しています。
2. 利用環境について
プロンプトがWindowsの標準のコマンドプロンプトではないですね。
rubyも含めcygwinでしょうか。
もしそうであればcygwin環境外で動作させるどうなりますか。
私の環境は次のとおりです。
> ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [i386-mingw32]
> gem list
easy_upnp (1.1.10)
OSはWindows 10 Pro 64bit
3. Wifiルータについて
Wifiルータに直接接続ということですが、スイッチングハブで有線接続してみて
状況は変わるでしょうか。
変わるようであればWifiルートが影響している可能性があります。
別のソフトでは問題なく動作しているということなので、可能性は低いかもしれ
ませんが。
4. Windowsのサービス設定
WindowsのSSDPサービスは有効でしょうか。
私の環境ではSSDPサービスが有効だとスクリプトが動作しますが、無効にする
と、Host Unreachable となって、そもそも送信できなくなります。
(これはWindows 7 Pro 64bit で確認)
SSDPはRFCにはなっていないようですが、アドレス指定の方法も一般のUDPブロー
ドキャストでも、マルチキャストでもない特殊な仕様のようですね。
5. ローカルポート確認
特殊な仕様であるものの、デバイスからのリプライは、PC側のローカルポートに
対するUDP通信になっているようです。
こちらでWiresharkのログを見る限り、デバイスからの送信元ポートは1900で
あったり、別のもの(デバイス側のローカルポートでしょう)であったり、機器
によって変わっています。
UDPなので、ポート番号さえ合っていれば受信できると思います。
そちらではWiresharkのログは取れているということでなので、send後のローカ
ルポート番号を確認して、Wireshark のログと突き合わせてみてはどうでしょうか。
ssdp_searcher.rb から最低限必要なところを取り出すと次のようになります。
sendのあとの行で、ローカルポート番号を確認できます。
またbindでローカルポートを固定することもできます。
(コメントアウトしてある行)
先のメールのとおり、IFの指定をしないとそもそもWiresharkのパケットも出ま
せん。以前はうまく言っていたのですが、その時点からVirtualBoxのインストー
ルやらアンイントールをしたりしているので、全く同じ環境ではなくなっている
のが影響したものと推測しています。
==== cut here
require 'socket'
require 'ipaddr'
packet =<<EOS
M-SEARCH * HTTP/1.1\r
HOST: 239.255.255.250:1900\r
MAN: "ssdp:discover"\r
MX: 1\r
ST: ssdp:all\r
\r
EOS
socket = UDPSocket.open
#socket.bind('0.0.0.0', 10000)
mif = IPAddr.new('192.168.11.24').hton
socket.setsockopt(:IPPROTO_IP, Socket::IP_MULTICAST_IF, mif)
socket.send(packet, 0, '239.255.255.250', 1900)
puts Socket.unpack_sockaddr_in(socket.getsockname)
loop do
data = socket.recv(8192)
puts "recv #{data.size} bytes"
end
=====
私見では環境(Cygwin?)が影響している可能性が高いのではと推測しています。
socket.rb には require 'socket.so' とあので。
市田