This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_extPart_001_01C11A1F.2CECF680
Content-Type: text/plain;
	charsetso-8859-1"

 
Something I threw together a few weeks ago. It has only been tested using
Ruby 1.7.1 on Win32, but It should work on the other platforms as well. You
may have to take out the definition of the constants since they should
already be defined in socket.c. There are some some differences in the C
headers #defines of these constants, but I did not have time to look into
this and fix it on Windows. 
 
enjoy...
 
- Will
 
<SNIP filenameulticast.rb' >

require 'socket'
 
#struct ip_mreq {
#        struct in_addr  imr_multiaddr;  /* IP multicast address of group */
#        struct in_addr  imr_interface;  /* local IP address of interface */
#};
 

class MulticastSocket < UDPSocket
 
 # Some constants that are not set in Win32 version of socket.c
 IPPROTO_IP  
 IPPROTO_UDP  7
 IP_DROP_MEMBERSHIP  
 
 def convAddr(a)
  h  il
  case a
  when String
   h  .split('.').collect! { |b| b.to_i }.pack('CCCC')
 
  when Array
   h  .pack('CCCC')
 
  else
   raise "Bad address"
  end
  h
 end
 private :convAddr
 
 def addMembership(mcaddr)
  mreq  onvAddr(mcaddr) + Socket.gethostbyname(Socket.gethostname)[3]
  setsockopt(IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, mreq)
 end
 
 def dropMembership(mcaddr)
  mreq  onvAddr(mcaddr) + Socket.gethostbyname(Socket.gethostname)[3]
  setsockopt(IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq)
 end
 
 def setMCTTL(ttl)
  setsockopt(IPPROTO_IP, Socket::IP_MULTICAST_TTL, ttl)
 end
 
 def setMCLoop(loop)
  setsockopt(IPPROTO_IP, Socket::IP_MULTICAST_LOOP, loop)
 end
 
 def setMCInterface(int)
  host  ocket.gethostbyname(int)[3]
  setsockopt(IPPROTO_IP, Socket::IP_MULTICAST_IF, host)
 end
 
end
 
if $0 __FILE__
 
 $port  900
 $addr  239.192.0.1'
 
 sock  ulticastSocket.open
 sock.bind(Socket.gethostname, $port)
 sock.addMembership($addr)
  
 thread  hread.start do
  2.times { p sock.recvfrom(8000) }
 end
 
 sock.send('Hello', 0, $addr, $port)
 sock.send('There', 0, $addr, $port)
 
 thread.join
 sock.dropMembership($addr)
end
 

</SNIP>

-----Original Message-----
From: Nat Pryce [mailto:nat.pryce / b13media.com]
Sent: Tuesday, July 31, 2001 5:09 AM
To: ruby-talk / ruby-lang.org
Subject: [ruby-talk:18883] IP multicast with UDPSocket


Does anyone have example code for joining/leaving multicast groups using the
UDPSocket?
 
Also, how is it possible to write this in a platform independent manner?  As
far as I can tell, the API for setting socket options seems to be completely
platform dependent.  It is also hard to code to, because you have to build
strings of binary data that contain valid C structures used by the OS APIs.
Would there be interest in code to replace or wrap setsockopt/getsockopt
with methods and attribute accessors?  
 
For example:
 
socket  DPSocket.new
socket.add_membership "240.212.100.200"  # or whatever a valid IP group
number is
socket.ip_multicast_ttl  ocket::TTL_LOCAL_NETWORK
socket.ip_multicast_loopback  alse
socket.sol_reuse_address  rue
socket.bind( 15630 )
 
Or:
 
socket  CPSocket.new( 'www.b13media.com', 80 )
socket.sol_sndbuf  12
socket.sol_rcvbuf  096
 
Would this be a useful RCR?
 
Cheers,
    Nat.
 
 


------_extPart_001_01C11A1F.2CECF680
Content-Type: text/html;
	charsetso-8859-1"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META HTTP-EQUIV
ontent-Type" CONTENText/html; charseto-8859-1"> <META contentSHTML 5.50.4134.600" nameۥʥޥ᥻ եʥåեʥ åͥʥȥ ĥޥȥ fffff> <DIV><FONT face ﰰ Ծ𻼯<DIV><SPAN class#4145223-31072001><FONT face ﰰ size Something I threw together a few weeks ago.&nbsp;It has only been tested&nbsp;using Ruby&nbsp;1.7.1 on Win32, but&nbsp;It should work on the other platforms as well. You may have to take out the definition of the constants since they should already be defined in socket.c. There are some&nbsp;some differences in the C headers #defines of these constants, but I did not have time to look into this and fix it&nbsp;on Windows. </FONT></SPAN></DIV> <DIV><SPAN class#4145223-31072001></SPAN><SPAN class#4145223-31072001><FONT face ﰰ Ծξ𻼯־ <DIV><SPAN class#4145223-31072001></SPAN><SPAN class#4145223-31072001><FONT face ﰰ Ծξ־ <DIV><SPAN class#4145223-31072001><FONT face ﰰ size </FONT></SPAN>&nbsp;</DIV> <DIV><SPAN class#4145223-31072001><FONT face ﰰ Will</FONT></SPAN></DIV> <DIV><SPAN class#4145223-31072001><FONT face ﰰ size </FONT></SPAN>&nbsp;</DIV> <DIV><SPAN class#4145223-31072001><FONT face ﰰ size &lt;SNIP filenameulticast.rb' &gt;</FONT></SPAN></DIV><SPAN class#4145223-31072001> <DIV><FONT face ﰰ Ծ ﰰ size </FONT><FONT face ﰰ Ծ color000ff size </FONT><FONT face ﰰ Ծ face ﰰ ԾҾ ﰰ size require 'socket'</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ {<BR>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct in_addr&nbsp; imr_multiaddr;&nbsp; /* IP multicast address of group */<BR>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct in_addr&nbsp; imr_interface;&nbsp; /* local IP address of interface */<BR>#};</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ Ծ ﰰ size </FONT><FONT face ﰰ Ծ color000ff size </FONT><BR><FONT face ﰰ MulticastSocket &lt; UDPSocket</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ set in Win32 version of socket.c<BR>&nbsp;IPPROTO_IP <BR>&nbsp;IPPROTO_UDP 17<BR>&nbsp;IP_DROP_MEMBERSHIP </FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ convAddr(a)<BR>&nbsp;&nbsp;h il<BR>&nbsp;&nbsp;case a<BR>&nbsp;&nbsp;when String<BR>&nbsp;&nbsp;&nbsp;h .split('.').collect! { |b| b.to_i }.pack('CCCC')</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ Array<BR>&nbsp;&nbsp;&nbsp;h .pack('CCCC')</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ size &nbsp;&nbsp;else<BR>&nbsp;&nbsp;&nbsp;raise "Bad address"<BR>&nbsp;&nbsp;end<BR>&nbsp;&nbsp;h<BR>&nbsp;end<BR>&nbsp;private :convAddr<BR>&nbsp;<BR>&nbsp;def addMembership(mcaddr)<BR>&nbsp;&nbsp;mreq convAddr(mcaddr) + Socket.gethostbyname(Socket.gethostname)[3]<BR>&nbsp;&nbsp;setsockopt(IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, mreq)<BR>&nbsp;end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ dropMembership(mcaddr)<BR>&nbsp;&nbsp;mreq onvAddr(mcaddr) + Socket.gethostbyname(Socket.gethostname)[3]<BR>&nbsp;&nbsp;setsockopt(IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq)<BR>&nbsp;end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ setMCTTL(ttl)<BR>&nbsp;&nbsp;setsockopt(IPPROTO_IP, Socket::IP_MULTICAST_TTL, ttl)<BR>&nbsp;end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ setMCLoop(loop)<BR>&nbsp;&nbsp;setsockopt(IPPROTO_IP, Socket::IP_MULTICAST_LOOP, loop)<BR>&nbsp;end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ setMCInterface(int)<BR>&nbsp;&nbsp;host Socket.gethostbyname(int)[3]<BR>&nbsp;&nbsp;setsockopt(IPPROTO_IP, Socket::IP_MULTICAST_IF, host)<BR>&nbsp;end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ 伯Ծ־ <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ ߼Ծ<DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ Ҿ Ծ־ <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ Ҿ $port)<BR>&nbsp;sock.addMembership($addr)<BR>&nbsp;&nbsp;<BR>&nbsp;thread Thread.start do<BR>&nbsp;&nbsp;2.times { p sock.recvfrom(8000) }<BR>&nbsp;end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ 䨧溺 $port)<BR>&nbsp;sock.send('There', 0, $addr, $port)</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ size &nbsp;thread.join<BR>&nbsp;sock.dropMembership($addr)<BR>end</FONT></DIV> <DIV><FONT face ﰰ Ծ𻼯<DIV><FONT face ﰰ Ծ ﰰ size </FONT><BR><SPAN class#4145223-31072001><FONT face ﰰ size &lt;/SNIP&gt;</FONT></SPAN></SPAN></DIV> <BLOCKQUOTE dirr styleARGIN-RIGHT: 0px"> <DIV classtlookMessageHeader dirr align˥ޥۥ إ奷ĥ᥻ĥ˥åĥ 祿󥷥ĥ᥻ĥ⥳åĥ إĥ᥻ĥ䥳åĥ 奿祷ĥ᥻ĥ⥳åĥ 女 Υ ȥߥ⥷ĥ᥻ĥ᥻å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ ȥߥ⥽å˥ޥۥ䥻åȥΥ襻 ȥΥ襻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻˥ޥۥ ߥ ޥ ߥΥ å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ ȥߥ祷å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 硬 ֥祤祢祤֥ Υ å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 硬 ⥳ץեޥƥץۥʥޥҥå˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 硬 å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 硬 å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 祣 å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ ޥå˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ ƥߥ祣 祢祡 å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 硬 å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 硬 å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ ƥ᥽å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ ƥ㥷å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ 򥵥򥵥 ۥ祷å˥ޥۥ䥻åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻 ȥΥ襻˥ޥۥ å˥ޥۥ䥻򥵥åȥΥ襻åĥեޥƥҥޥʥåĥޥȥ륻åͥإե 塬ߡƥ˥祤ƥʥƥ˥