ããããããã«ããã£ã¹ãã䜿ã£ããããã¯ãŒã¯ããã°ã©ãã³ã°ã«ã
ãããŸã§ãDatagramSocketã¯ã©ã¹ã䜿ã£ãããã°ã©ã ã¯ãçžæãã²ãšãããããªãããŠããã£ã¹ãã§ããããä»åºŠã¯è€æ°ã®çžæã«éä¿¡ãããã«ããã£ã¹ãã§ãã
ïŒDatagramSocketã¯ã©ã¹ã§ããã«ããã£ã¹ãã䜿ããªããšããããã§ã¯ãªãã§ããâŠ
æ£ããã¯ã1åã®éä¿¡ã§è€æ°ã®ã¡ã³ããŒãåä¿¡ã§ãããšèšã£ãæ¹ãããã§ããããã
ãã«ããã£ã¹ãã¢ãã¬ã¹ã¯è€æ°ã®ã¢ãã¬ã¹ãåå ããŠããã°ã«ãŒãã§ããã®ã°ã«ãŒãã«åã ã®ã¡ã³ããŒãåå ïŒjoinïŒããããéåºïŒleaveïŒãããã§ããŸããã€ãŸããã°ã«ãŒãã®æ§æã¡ã³ããŒã¯åçã«å€ããããã§ããã
ãã«ããã£ã¹ãã¢ãã¬ã¹ã¯ã224.0.0.0ã239.255.255.255ãŸã§ã®ç¯å²ã ããã§ãããã«224.0.0.0ã224.0.0.255ã¯äºçŽãããŠãããããã§ãã
ãŸããã¹ã³ãŒããšããæŠå¿µããããTTLã䜿ãããšãã§ããŸããã¹ã³ãŒããšããŠã¯ã
ã¹ã³ãŒã | 説æ |
---|---|
ããŒãããŒã«ã«ïŒnode-localïŒ | ãã®ããŒã«ã«ããŒããè¶ããŠã¯ãªããªãïŒãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ãŒã¹ããåºåãããªã |
ãªã³ã¯ããŒã«ã«ïŒlink-local) | ã«ãŒã¿ã®åããåŽãžã¯åºãŸããªã |
ãµã€ãããŒã«ã«ïŒsite-localïŒ | ãµã€ãã®å€ãžåºãŸããªãããµã€ãã¯ãããã¯ãŒã¯ç®¡çè ã®å®çŸ©ã«ãã |
çµç¹ããŒã«ã«ïŒorganization-localïŒ | çµç¹ã®å€ãžåºãŸããªããçµç¹ã®å®çŸ©ã¯ããã®çµç¹ã®ãããã¯ãŒã¯ç®¡çè ã®å®çŸ©ã«ãã |
åºåããŒã«ã«ïŒregion-localïŒ | åºåãšå®çŸ©ãããŠããç¯å²ã®å€ãžåºãŸããªã |
倧éžããŒã«ã«ïŒcontinent-localïŒ | 倧éžãšå®çŸ©ãããŠããç¯å²ã®å€ãžåºãŸããªã |
ã°ããŒãã«ïŒglobalïŒ | ã©ããžã§ãåºãŸã |
ããããŸããããã§ã®ã¹ã³ãŒãã«ã¯ãIPv4ãšIPv6ã®ã¹ã³ãŒããæ··åšããŠãããšâŠãTTLã䜿ã£ãã¹ã³ãŒãã¯åçãªã¹ã³ãŒãã§ãã¹ã³ãŒãã®å®çŸ©ãšç §ããåããããš
TTL | ã¹ã³ãŒã |
---|---|
0 | ããŒãããŒã«ã« |
1 | ãªã³ã¯ããŒã«ã« |
< 32 | ãµã€ãããŒã«ã« |
< 64 | åºåããŒã«ã« |
< 128 | 倧éžããŒã«ã« |
< 255 | ã°ããŒãã« |
ãšãªãããã§ãããªããTTLã®ããã©ã«ãå€ã¯1ã§ãMulticastSocket#setTimeToLiveã§èšå®ããããšãã§ããŸãããTTLèªäœãIPv4ã®ã¿ã§ãã䜿ããŸããã
ã¯ããã§ã¯ãããã°ã©ã ã«ãã£ãŠã¿ãŸãããããé¡ãšããŠãèªèº«ããã«ããã£ã¹ãã°ã«ãŒãã«åå ããŠããã«ããã£ã¹ããåä¿¡ãã€ã€ãéä¿¡ãè¡ããã£ããããã°ã©ã çãªãã®ãäœã£ãŠã¿ãŸãã
udp_mcast_member.clj
(import '(java.net DatagramPacket InetAddress InetSocketAddress MulticastSocket NetworkInterface SocketTimeoutException) '(java.util Date)) (require '[clojure.string :as str]) (def port 7600) (def address (InetSocketAddress. (InetAddress/getByName "228.8.8.8") port)) (def timeout 500) (def receive-continually (ref true)) (defn log [word & more-words] (println (str \[ (Date.) \] \ word (str/join \ more-words)))) (with-open [socket (MulticastSocket. port)] (.setSoTimeout socket timeout) (doseq [intf (enumeration-seq (NetworkInterface/getNetworkInterfaces))] (.joinGroup socket address intf)) (log "Clojure Multicast Chat Application, Startup." \[ address \]) (letfn [(receive [] (loop [] (if @receive-continually (do (try (let [buffer (byte-array 8192) packet (DatagramPacket. buffer 0 (alength buffer))] (.receive socket packet) (println (str "message => " (String. (.getData packet) (.getOffset packet) (.getLength packet) "UTF-8")))) (catch SocketTimeoutException _)) (recur)) (do (doseq [intf (enumeration-seq (NetworkInterface/getNetworkInterfaces))] (.leaveGroup socket address intf)) (log "Leave Multicast Group Completed."))))) (read-and-send [reader] (loop [] (let [word (reader)] (case word nil (recur) "" (recur) "_exit_" (do (dosync (ref-set receive-continually false))) (do (let [word-binary (.getBytes word "UTF-8")] (.send socket (DatagramPacket. word-binary 0 (alength word-binary) address)) (recur)))))))] (let [threads [(Thread. receive) (Thread. #(read-and-send read-line))]] (doseq [t threads] (.start t)) (doseq [t threads] (.join t)))))
ãã«ããã£ã¹ããåä¿¡ããããã«ã¯ãMulticastSocketã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
(with-open [socket (MulticastSocket. port)]
ç¶ããŠããã«ããã£ã¹ãã°ã«ãŒãã«MulticastSocket#joinGroupã¡ãœããã§åå ããŸããããã§ã¯ããã¹ãŠã®ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ãŒã¹ã§ãã«ããã£ã¹ãã°ã«ãŒãã«åå ããŠããŸãã
(doseq [intf (enumeration-seq (NetworkInterface/getNetworkInterfaces))] (.joinGroup socket address intf))
ããšã¯ãæ®éã«MulticastSocket#receiveã¡ãœããã§ãã«ããã£ã¹ãã®åä¿¡ãã§ããŸãã
(.receive socket packet)
ãã«ããã£ã¹ãã°ã«ãŒãããéåºããæã¯ãMulticastSocket#leaveGroupã¡ãœããã䜿çšããŸãã
(doseq [intf (enumeration-seq (NetworkInterface/getNetworkInterfaces))] (.leaveGroup socket address intf))
ã¡ãªã¿ã«ãMulticastSocketã¯ã©ã¹ã¯DatagramSocketã¯ã©ã¹ã®ãµãã¯ã©ã¹ã§ãã
ããŒã¿ã®éä¿¡ã¯ãMulticastSocket#sendã¡ãœããã§è¡ããŸãããŸããããã¯å¥ã«MulticastSocketã¯ã©ã¹ã䜿ããªããŠãããã®ã§ããã
(.send socket (DatagramPacket. word-binary 0 (alength word-binary) address))
ãããŠãä»åã®ããã°ã©ã ã¯ã¹ã¬ããã2ã€äœ¿ã£ãŠãçæ¹ãåä¿¡çšã«ãããçæ¹ãéä¿¡æ§ã«äœ¿ã£ãŠããŠäœãå ¥åããããŸãã¯ã_exit_ããšå ¥åããŠEnterãæŒããŸã§å®è¡ãç¶ããŸãã
ã§ã¯ãåãããŠã¿ãŸãããã
# ã²ãšã€ã $ clj udp_mcast_member.clj [Wed Sep 25 23:11:13 JST 2013] Clojure Multicast Chat Application, Startup.[ /228.8.8.8:7600 ] # ãµãã€ã $ clj udp_mcast_member.clj [Wed Sep 25 23:11:44 JST 2013] Clojure Multicast Chat Application, Startup.[ /228.8.8.8:7600 ]
èµ·åããããã©ã¡ããçæ¹ã®ã³ã³ãœãŒã«ã§æåãå ¥åããŠã¿ãŸãã
# ã²ãšã€ãã®æ¹ã§ Hello Multicast!! message => Hello Multicast!! ããã«ã¡ã¯ã message => ããã«ã¡ã¯ã äžç message => äžç _exit_ [Wed Sep 25 23:14:29 JST 2013] Leave Multicast Group Completed.
ã_exit_ããšå ¥åããŠEnterãæŒããã®ã§ãããã§çµäºã§ãã
ããçæ¹ã§ã¯
message => Hello Multicast!! message => ããã«ã¡ã¯ã message => äžç
ãšã¡ãã»ãŒãžã ãåºåãããŠããŸãã
äžå¿ãæåã§ããã
ãªããå ã«å°ãè§ŠããŸãããããã«ããã£ã¹ãã°ã«ãŒãã«ããŒã¿ãéä¿¡ããã ããªããMulticastSocketã¯ã©ã¹ã䜿ãå¿ èŠã¯ãããŸããã
ãããŸã§ãMulticastSocketã¯ã©ã¹ãå¿ èŠãªã®ã¯ãã°ã«ãŒãã«åå ããŠããŒã¿ãåä¿¡ãããæã§ããã
ãã¡ãã¯ããã«ããã£ã¹ãã°ã«ãŒãã«ããŒã¿ãéä¿¡ããã ãã®ããã°ã©ã ã§ãã
udp_sender.clj
(import '(java.net DatagramPacket DatagramSocket InetAddress InetSocketAddress) '(java.util Date)) (require '[clojure.string :as str]) (def port 7600) (def address (InetSocketAddress. (InetAddress/getByName "228.8.8.8") port)) (defn log [word & more-words] (println (str \[ (Date.) \] \ word (str/join \ more-words)))) (with-open [socket (DatagramSocket.)] (log "Multicast Message Sender" "Startup.") (doseq [word (take-while #(not (or (nil? %) (empty? %) (= % "_exit_"))) (repeatedly read-line))] (let [word-binary (.getBytes word "UTF-8")] (.send socket (DatagramPacket. word-binary 0 (alength word-binary) address)))))
éä¿¡å ãããã«ããã£ã¹ãã°ã«ãŒãã®ã¢ãã¬ã¹ãšããŒãã«åãããŠããã°ãåãåãå ã®ã¡ã³ããŒããããã°åä¿¡ããŠãããŸãã
ä»åã¯ãæå€ãšç°¡åã«ã§ããŸããã
ãããŠãæ¯åºŠãäžè©±ã«ãªããŸãããã®æžç±ããã«ããã£ã¹ãã®èª¬æããã»ãŒããããæã£ãŠããŠããŸãã

Javaãããã¯ãŒã¯ããã°ã©ãã³ã°ã®çé«
- äœè : ãšãºã¢ã³ãã»ããã,岩谷å®
- åºç瀟/ã¡ãŒã«ãŒ: ãœãããã³ã¯ ã¯ãªãšã€ãã£ã
- çºå£²æ¥: 2007/04/28
- ã¡ãã£ã¢: 倧忬
- è³Œå ¥: 9人 ã¯ãªãã¯: 100å
- ãã®ååãå«ãããã° (25ä»¶) ãèŠã
åããã ããªãç°¡åãªã®ã§ããããã£ã±ãUDPãªã®ã§çžæã«ã¡ãããšå±ãããšãä¿èšŒãããŠããããã§ã¯ãããŸããããã«ããã£ã¹ãã§é«ä¿¡é Œåã®ãããã³ã«ãäœãã®ã¯ãçžæã倿°ïŒãããã誰ãåå ããŠããã¯MulticastSocketã ãã§ã¯ããããªãïŒãªã®ã§ãããããå®çŸããã®ã¯é£ããã§ãããâŠã
æåŸããŠããã£ãã®ããªã©ã€ãçã®Scalaã§âŠãã¡ãã¯ãæšæºã©ã€ãã©ãªã®äœ¿ãæ¹ãééã£ãŠããã ããªãã§ããã©ãâŠã
UdpMulticast.scala
import scala.annotation.tailrec import scala.collection.JavaConverters._ import java.net.{DatagramPacket, DatagramSocket, InetAddress, InetSocketAddress, MulticastSocket} import java.net.{NetworkInterface, SocketAddress, SocketTimeoutException} import java.nio.charset.StandardCharsets import java.util.Date import java.util.concurrent.atomic.AtomicBoolean import UdpHelper._ object UdpHelper { val PORT: Int = 7600 val ADDRESS: SocketAddress = new InetSocketAddress(InetAddress.getByName("228.8.8.8"), PORT) def log(msg: Any, msgs: Any*): Unit = println(s"[${new Date}] ${(msg :: msgs.toList).mkString(" ")}") implicit class AutoCloseableWrapper[A <: AutoCloseable](val underlying: A) extends AnyVal { def foreach(fun: A => Unit): Unit = try { fun(underlying) } finally { underlying.close() } } } object UdpMcastMember { val timeout: Int = 500 val receiveContinually: AtomicBoolean = new AtomicBoolean(true) def main(args: Array[String]): Unit = for (socket <- new MulticastSocket(PORT)) { socket.setSoTimeout(timeout) NetworkInterface.getNetworkInterfaces.asScala.foreach { intf => socket.joinGroup(ADDRESS, intf) } log("Scala Multicast Chat Application, Startup.", '[', ADDRESS, ']') val threads = Array(new Thread { override def run(): Unit = receive(socket) }, new Thread { override def run: Unit = readAndSend(socket, readLine) }) threads.foreach(_.start()) threads.foreach(_.join()) } @tailrec private def readAndSend(socket: MulticastSocket, reader: => String): Unit = reader match { case word if word == null || word.isEmpty => readAndSend(socket, reader) case word if word == "_exit_" => receiveContinually.set(false) case word => val wordBinary = word.getBytes(StandardCharsets.UTF_8) socket.send(new DatagramPacket(wordBinary, 0, wordBinary.size, ADDRESS)) readAndSend(socket, reader) } @tailrec private def receive(socket: MulticastSocket): Unit = receiveContinually.get match { case false => NetworkInterface.getNetworkInterfaces.asScala.foreach { intf => socket.leaveGroup(ADDRESS, intf) } log("Leave Multicast Group Complete.") case true => try { val buffer = Array.ofDim[Byte](8192) val packet = new DatagramPacket(buffer, 0, buffer.size) socket.receive(packet) println("message => " + new String(packet.getData, packet.getOffset, packet.getLength, StandardCharsets.UTF_8)) } catch { case _: SocketTimeoutException => } receive(socket) } } object UdpSender { def main(args: Array[String]): Unit = for (socket <- new DatagramSocket) { log("Multicast Message Sender", "Startup.") Iterator .continually(readLine()) .takeWhile(word => word != null && !word.isEmpty && word != "_exit_") .foreach { word => val wordBinary = word.getBytes(StandardCharsets.UTF_8) socket.send(new DatagramPacket(wordBinary, 0, wordBinary.size, ADDRESS)) } } }