Andy自身でネットワークに繋がるなら、インターネット越しの遠隔制御したい、と思うところです。しかもカメラついてたら、楽しそうだし。。
さて、インターネットを介して複数の機器が連携したい場合、それぞれにグローバルIPが割当たっていれば特に問題なく通信はできるでしょうけれども、もし、それぞれの機器がルーターにぶら下がっているような場合、中継サーバなどを用いない場合、直接機器間で通信をどのように確立するか?という課題が発生します。
そこで、オールマイティな手法ではないようですが、大抵のルーター環境で使えそうなのが、UDP Hole Punchingという手法ということのようです。
この手法を使用すると、たとえばルーターAに繋がった機器aとルーターBに繋がった機器b同士が、ダイレクトにUDP通信できる、ということでした。いわゆる「NAT越え」の手法の一つだそうです。
UDPホールパンチングの何故UDPのパケットをダイレクトに機器間でやりとりできるか?の理屈は、ググるといろいろ出てきますので端折るとして、実際にコードを作成し、パケットを送受信させてみて、どんな感じか実験してみることにします。
ネットワークA : イーモバのポケットルーターに繋がってるPC1
ネットワークB : 光回線+バッファロールーターに繋がってるPC2
PC1とPC2とでUDPで直接お話し出来してみる、という実験です。
とりあえず、Rubyにて、実験用のコードを作ってみます。
PC1で1st.rb <ネットワークBのグローバルIP>として起動します。
次に、PC2で2nd.rb <ネットワークAのグローバルIP>として起動します。
すると、1st.rb側で既に開いてる穴に向かって2nd.rbからのUDPパケットが到着します。
1st.rb側は、2nd.rbからのUDPパケットの送信元情報を使用して、2nd.rb側に
パケットを投げますと、同様に2nd.rb実行側にも穴が開いてるのでパケットが届きます。
というわけで、いとも簡単にNAT越えできちゃいました!
実際に複数の機器間通信をやりたい時には、接続相手の管理をインターネット上の別サーバに行わせた上で、機器同士が通信をはじめれば良いのでしょうね。
1st.rb
#!/usr/bin/ruby require "socket" ipaddr = ARGV[0] port = 25000 printf("Accessing to %s:%d...",ipaddr,port) STDOUT.flush udp = UDPSocket.open() sockaddr = Socket.pack_sockaddr_in(port,ipaddr) udp.bind("0.0.0.0",port) udp.send("Hello",0,sockaddr) count = 0 msg,inet_addr = udp.recvfrom(65535) printf("Packet received.message=[%s]\n",msg) p inet_addr sockaddr2 = Socket.pack_sockaddr_in(port,inet_addr[3]) while(true) udp.send(sprintf("Send from 1st.rb:Count %8d\n",count),0,sockaddr2) count += 1 sleep(0.5) p udp.recv(65535) end udp.close2nd.rb
#!/usr/bin/ruby require "socket" ipaddr = ARGV[0] port = 25000 udp = UDPSocket.open() sockaddr = Socket.pack_sockaddr_in(port,ipaddr) udp.bind("0.0.0.0",port) udp.send("Hello",0,sockaddr) count = 50000 while(true) udp.send(sprintf("Send from 2nd.rb:Count %8d\n",count),0,sockaddr) count += 1 p udp.recv(65535) end udp.close
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
posted with amazlet at 12.08.21
Dustin Boswell Trevor Foucher
オライリージャパン
売り上げランキング: 325
オライリージャパン
売り上げランキング: 325
たのしいRuby 第3版
posted with amazlet at 12.08.21
高橋 征義 後藤 裕蔵
ソフトバンククリエイティブ
売り上げランキング: 6858
ソフトバンククリエイティブ
売り上げランキング: 6858