Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Introduction of Happy Eyeballs Version 2 (RFC83...

Introduction of Happy Eyeballs Version 2 (RFC8305) to the Socket library

Ruby Association Activity Report
「socketライブラリへのHappy Eyeballs Version 2 (RFC8305)の導入」報告資料

参考資料:HEv2の状態を洗い出すために作成した疑似コード
https://gist.github.com/shioimm/fbb09f103caf0812137c5c67ffa14eb6

More Decks by Misaki Shioi(塩井美咲/しおい)

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ ◼︎ ԘҪඒ࡙ ͓͍͠  ◼︎ !TIJPJNN (JU)VC  ◼︎

    !DPF@ 5XJUUFS !DPF #MVFTLZ  ◼︎ 8FCΞϓϦέʔγϣϯϓϩάϥϚɺ3VCZJTU ◼︎ גࣜձࣾΤεɾΤϜɾΤεɹϓϩμΫτ։ൃ෦ ◼︎ ஍Ҭ3VCZίϛϡχςΟ"TBLVTBSCϝϯόʔ
  2. ຊϓϩδΣΫτͰղܾ͍ͨ͠՝୊  ◼︎ ઀ଓࢼߦͷஈ֊ʹ͓͚Δ՝୊ લఏ  ղܾࡁΈͷ*1ΞυϨεͻͱͭͣͭʹରͯ͠ʮ௚ྻʹʯϦΫΤετΛ ૹ৴͢Δ Ѽઌαʔόͷ*1ΞυϨε΁ϦΫΤετΛૹ৴ͨ͠ޙɺ αʔό͕ଈ࠲ʹϨεϙϯεΛฦ͞ͳ͍৔߹ɺ

    ΫϥΠΞϯτ͸઀ଓͷཱ֬·ͨ͸ࣦഊ͕֬ఆ͢Δ·Ͱಈ࡞Λఀࢭ͢Δ ʹղܾࡁΈͷ*1ΞυϨε͕ෳ਺͋ͬͨͱͯ͠΋ɺ ɹ଴ػதʹଞͷ*1ΞυϨεѼͷ઀ଓΛࢼΈΔ͜ͱ͕Ͱ͖ͳ͍
  3. )BQQZ&ZFCBMMT7FSTJPO )&W ΞϧΰϦζϜ *OJUJBUJPOPGBTZODISPOPVT%/4RVFSJFT ɹɹɹ ඇಉظͰ%/4໰͍߹ΘͤΛ։࢝͢Δ  4PSUJOHPGSFTPMWFEEFTUJOBUJPOBEESFTTFT ɹɹɹ औಘͨ͠ΞυϨεΛιʔτ͢Δ

     *OJUJBUJPOPGBTZODISPOPVTDPOOFDUJPOBUUFNQUT ɹɹɹ ඇಉظͰ͜ΕΒͷΞυϨεʹର͢Δ઀ଓࢼߦΛ։࢝͢Δ  &TUBCMJTINFOUPGPOFDPOOFDUJPO  XIJDIDBODFMTBMMPUIFSBUUFNQUT ɹɹɹ ͍ͣΕ͔ͷ઀ଓཱ͕֬ͨ͠ΒɺͦΕҎ֎͸Ωϟϯηϧ͢Δ )BQQZ&ZFCBMMT7FSTJPO#FUUFS$POOFDUJWJUZ6TJOH$PODVSSFODZ0WFSWJFX IUUQTEBUBUSBDLFSJFUGPSHEPDIUNMSGDTFDUJPO
  4. )&Wಋೖޙͷಈ࡞γφϦΦ ྫᶃ ϝΠϯεϨου͔ΒࢠεϨουΛೋͭੜ੒͠ɺ ֤εϨου಺ͰͦΕͧΕ*1W*1Wͷ໊લղܾΛ։࢝ ͍ͣΕ͔ͷΞυϨεϑΝϛϦͷ໊લղܾΛ଴ػ ઌʹ*1Wͷ໊લղܾ͕׬ྃ *1WΞυϨεѼʹ઀ଓΛ։࢝ *1WΞυϨεѼͷ઀ଓཱ͔֬*1WͷΞυϨεͷ໊લղܾΛ଴ػ *1Wͷ໊લղܾ͕׬ྃ 

    ᫔᫓ճආͷͨΊNTܦաޙ *1WΞυϨεѼͷ઀ଓΛ։࢝ *1WΞυϨεѼͷ઀ଓʹࣦഊ *1WΞυϨεѼͷ઀ଓΛ଴ػ *1WΞυϨεѼͷ઀ଓʹ੒ޭ ໊લղܾ   ઀ଓ  Λ։࢝ ໊લղܾ  ͕׬ྃɺ*1WΞυϨεѼͷ઀ଓ͕ՄೳʹͳΔ ઀ଓ  Λ։࢝ ઀ଓ  ʹࣦഊ ઀ଓ  ʹ੒ޭ
  5. )&Wಋೖޙͷಈ࡞γφϦΦ ྫᶄ ϝΠϯεϨου͔ΒࢠεϨουΛೋͭੜ੒͠ɺ ֤εϨου಺ͰͦΕͧΕ*1W*1Wͷ໊લղܾΛ։࢝ ͍ͣΕ͔ͷΞυϨεϑΝϛϦͷ໊લղܾΛ଴ػ ઌʹ*1Wͷ໊લղܾ͕׬ྃ  *1WͰͷ઀ଓΛ༏ઌ͢ΔͨΊ *1Wͷ໊લղܾΛNT଴ػ *1Wͷ໊લղܾ͕׬ྃ

    *1WΞυϨεѼʹ઀ଓΛ։࢝  ᫔᫓ճආͷͨΊNTܦաޙ *1WΞυϨεѼͷ઀ଓࢪߦΛ։࢝ *1WΞυϨεѼ઀ଓʹࣦഊͨ͜͠ͱ͕֬ఆ *1WΞυϨεѼͷ઀ଓΛ଴ػ *1WΞυϨεѼͷ઀ଓʹ੒ޭ ໊લղܾ   ໊લղܾ  ͕׬ྃ ઀ଓ  Λ։࢝ ઀ଓ  ʹࣦഊ ઀ଓ  ʹ੒ޭ
  6. ঢ়ଶͷҰཡ WD GBJMVSF WX TVDDFTT WD WD TUBSU WX UJNFPVU

    ʜ։࢝࣌఺Ͱͷঢ়ଶɻ໊લղܾΛ։࢝͢Δ ʜ໊લղܾ·ͨ͸઀ଓͷ׬ྃΛ଴ػ͢ΔͨΊͷঢ়ଶ ʜ઀ଓΛ։࢝͢ΔͨΊͷঢ়ଶ ʜऴྃ࣌ʹࢸΔঢ়ଶ
  7. ঢ়ଶͷ঺հ  WX ʜ઀ଓͷ׬ྃΛ଴ػ͢Δ ɹ·໊ͩલղܾ͕ऴΘ͍ͬͯͳ͍ΞυϨεϑΝϛϦ͕͋Δ৔߹ɺ ɹಉ࣌ʹ໊લղܾͷ׬ྃ΋଴ػ͢Δ ɹ ଴ػ࣌ؒલճͷ઀ଓ։͔࢝ΒNTܦա͢Δ·Ͱ  ɹɾنఆͷ଴ػ࣌ؒ಺ʹ઀ଓ͕׬ྃͨ͠৔߹

    ➡︎ TVDDFTT΁ભҠ ɹɾنఆͷ଴ػ࣌ؒ಺໊લղܾ͕׬ྃͨ͠৔߹ ➡︎ ࠶ͼWX΁ભҠ ɹɹ˞໊લղܾ͕׬ྃͨ͠৔߹͸WD΁ભҠͯ͠৽͍͠઀ଓΛ։͍͕࢝ͨ͠ɺ ɹɹɹ᫔᫓ճආͷͨΊʹWXͰنఆ࣌ؒ NT ܦա͢Δ·Ͱ଴ػ͢Δ ɹɹɹ଴ػ࣌ؒΛܦաͨ͠ΒWD΁ભҠ ɹɾنఆͷ଴ػ࣌ؒΛܦաͨ͠৔߹ɿ ɹɹɹະ઀ଓͷΞυϨε͕࢒͍ͬͯΔ ➡︎ WD΁ભҠ ɹɹɹະ઀ଓͷΞυϨε͕࢒͍ͬͯͳ͍ ➡︎ ࠶ͼWX΁ભҠ
  8. UJNFPVU GBJMVSF TVDDFTT ঢ়ଶͷ঺հ  ʜ WDɺWDɺWD·ͨ͸WX͔ΒભҠ  ɹ઀ଓʹ੒ޭɺιέοτΛฦ͢ ʜ

    TUBSUɺWDɺWDɺWD·ͨ͸WX͔ΒભҠ  ɹ͢΂ͯͷ໊લղܾ·ͨ͸͢΂ͯͷ઀ଓࢼߦʹࣦഊɺྫ֎ൃੜ ʜ TUBSUɺWDɺWDɺWD·ͨ͸WX͔ΒભҠ  ɹϢʔβʔࢦఆͷλΠϜΞ΢τʹͯྫ֎ൃੜ
  9. ࣮૷ͷେ࿮ 4PDLFUUDQ def self.tcp(host, port, ...) # ... state =

    :start loop do case state when :start # ... state = :v6c when :v4w # ... when :v6c, :v4c, :v46c # ... when :v46w # ... when :success # ... end end ,FSOFMMPPQͱDBTFจͷ૊Έ߹ΘͤʹΑΓঢ়ଶભҠΛදݱ͢Δ ϧʔϓ಺Ͱঢ়ଶʹԠͯ͡ॲཧΛߦ͍ɺ৽͍͠ঢ়ଶΛઃఆ͠ɺ ࣍ͷϧʔϓʹೖΔ ϧʔϓʹ͖ͭঢ়ଶભҠΛදݱ ঢ়ଶΛTUBSUʹॳظԽ
  10. ࣮૷ͷେ࿮ 4PDLFUUDQ ໊લղܾͷ։࢝ case state when :start # ... queue

    = HostnameResolutionQueue.new # ... Thread.new(host, port, queue) { |*args| hostname_resolution(*args) } # ... ΞυϨεϑΝϛϦ͝ͱʹεϨουΛੜ੒͠ɺ ࢠεϨουͷதͰฒߦʹ໊લղܾ༻ϝιουΛ࣮ߦ  ࢠεϨουʹ͸͋Β͔͡Ί࡞੒ͨ͠QJQFΛ౉͓ͯ͘͠ class HostnameResolutionQueue def initialize(size) # ... @rpipe, @wpipe = IO.pipe ༧ΊQJQFΛ࡞੒͓͖ͯ͠ɺ εϨουͷҾ਺ʹ౉͢
  11. ࣮૷ͷେ࿮ 4PDLFUUDQ ໊લղܾͷ։࢝ # ࢠεϨουͰݺͼग़໊͢લղܾ༻ϝιου de begin resolved_addrinfos = Addrinfo.getaddrinfo(

    host, port, ADDRESS_FAMILIES[family], :STREAM ) hostname_resolution_queue.add_resolved( family, resolved_addrinfos ) rescue => e # ... end  ࢠεϨου  ໊લղܾ༻ϝιουͰ͸"EESJOGPHFUBEESJOGPΛݺͼɺ ͦͷ׬ྃ࣍ୈQJQFͷॻ͖ࠐΈଆʹͦͷࢫΛ௨஌͢Δ ໊લղܾϝιου͕ऴྃ͢ΔͱɺࢠεϨου͸ऴྃ ໊લղܾΛ࣮ߦ ໊લղܾͷ׬ྃΛQJQFʹ௨஌ def add_resolved(family, resolved_addrinfos) @mutex.synchronize do @queue.push [family, resolved_addrinfos] @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED # ... ef self.hostname_resolution(family, host, port, hostname_resolution_queue)
  12. ࣮૷ͷେ࿮ 4PDLFUUDQ ໊લղܾͷ଴ػ case state when :start # ... queue

    = HostnameResolutionQueue.new # ... Thread.new(host, port, queue) { |*args| hostname_resolution(*args) } # ... hostname_resolved, _, = IO.select(rpipe, nil, nil, nil) family_name, res = hostname_resolution_queue.get selectable_addrinfos.add(family_name, res) state = :v6c # ... next  ϝΠϯεϨου  *0TFMFDUͰQJQF΁ͷॻ͖ࠐΈ໊લղܾΛ଴ػ ໊લղܾ׬ྃޙɺղܾͰ͖ͨΞυϨεΛอଘ͢Δ *0TFMFDUʹQJQFͷಡΈࠐΈଆΛ౉͢ εϨου಺Ͱ໊લղܾ͕׬ྃ࣍ୈɺ QJQFͷಡΈࠐΈଆ͕४උ׬ྃʹͳΓ *0TFMFDU͕଴ػΛղআ͢Δ ࣍ͷঢ়ଶΛઃఆ औಘͨ͠*1ΞυϨεΛอଘ ࣍ͷϧʔϓ΁ ແ੍ݶʹ଴ػ
  13. case state when :v4w ipv6_resolved, _, = IO.select( if ipv6_resolved

    family_name, res = hostname_resolution_queue.get selectable_addrinfos.add(family_name, res) unless res.is_a? E state = :v46c else state = :v4c end next # ... ࣮૷ͷେ࿮ 4PDLFUUDQ ໊લղܾͷ଴ػ ઌʹ*1WΞυϨεΛղܾͰ͖ͨ৔߹ ಉ͘͡*0TFMFDUΛ༻͍ͯ*1WΞυϨεͷղܾΛ଴ػ͢Δ ࣍ͷঢ়ଶΛઃఆ ࣍ͷϧʔϓ΁ Exception (hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY) 3&40-65*0/@%&-":NT
  14. ࣮૷ͷେ࿮ 4PDLFUUDQ ઀ଓͷ։࢝ case state when :v6c, :v4c, v46c #

    ... addrinfo = selectable_addrinfos.get # ... connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY # ... socket = Socket.new( socket.bind(local_addrinfo) if local_addrinfo result = socket.connect_nonblock(addrinfo, exception: false) # ... case result # ... end next ෳ਺ͷΞυϨεѼͷ઀ଓࢼߦΛฒߦʹߦ͏Մೳੑ͕ ͋ΔͨΊɺ4PDLFUDPOOFDU@OPOCMPDLΛ࢖༻ͯ͠ ϊϯϒϩοΩϯάϞʔυͰ઀ଓΛ։࢝ ղܾࡁΈͷ*1ΞυϨεΛऔಘ ϊϯϒϩοΩϯάϞʔυͰ઀ଓΛ։࢝ ࣍ͷϧʔϓ΁ ࣍ͷঢ়ଶΛઃఆ
  15. case state when :v46w # ... hostname_resolved, connectable_sockets, = IO.select(

    # ... (rpipe, connecting_sockets.all, nil, remaining) ઀ଓதͷιέοτ ઀ଓͷ଴ػ  *0TFMFDUΛར༻ͯ͠઀ଓͱ໊લղܾͷ׬ྃΛಉ࣌ʹ଴ػ  ଴ػ࣌ؒલճͷ઀ଓ։͔࢝ΒNTܦա͢Δ·Ͱ ͜ͷ࣌఺Ͱ͸ยํͷΞυϨεϑΝϛϦͷ໊લղܾ͕׬͍ྃͯ͠ͳ͍Մೳੑ͋Γ ࣮૷ͷେ࿮ 4PDLFUUDQ ઀ଓ໊લղܾͷ଴ػ *0QJQFͰ࡞੒ͨ͠ύΠϓͷ ಡΈࠐΈଆ ໊લղܾͷ଴ػ   ઀ଓΛࢼ͍ͯ͠ͳ͍ΞυϨε͕͋Δ৔߹  ࣍ͷ઀ଓΛ։࢝Ͱ͖Δ·Ͱͷ࢒Γ࣌ؒ
  16. def self.tcp(host, port, ...) # ... ret = loop do

    case state # ... when :success break connected_socket when :failure raise last_error when :timeout raise Errno::ETIMEDOUT, "user specified timeout" end end if block_given? begin yield ret ensure ret.close end else ret end end ঢ়ଶભҠͷऴྃঢ়ଶΛܦ༝ͯ͠ɺ ϧʔϓ͔Βൈ͚Δ͔ྫ֎Λൃੜͤ͞Δ  ϧʔϓ͔Βൈ͚ͨ৔߹͸઀ଓࡁΈιέοτΛฦͯ͠ऴྃ ऴྃঢ়ଶ ઀ଓࡁΈͷιέοτΛฦ͢ ࣮૷ͷେ࿮ 4PDLFUUDQ ऴྃॲཧ
  17. தஅՄೳͳHFUBEESJOGPͷ಺෦࣮૷ 3VCZ࣌఺ ▫໊લղܾϝιουͷίʔϧελοΫ ɾ4PDLFUHFUBEESJOGP ɹ ➡︎ TPDL@T@HFUBEESJOGP ɹɹ ➡︎ STPDL@HFUBEESJOGP

    ɾ"EESJOGPHFUBEESJOGP ɹ ➡︎ BEESJOGP@T@HFUBEESJOGP ɹɹ ➡︎ BEESJOGP@MJTU@OFX ɹɹɹ ➡︎ DBMM@HFUBEESJOGP ɹɹɹɹ ➡︎ STPDL@HFUBEESJOGP ڞ௨
  18. தஅՄೳͳHFUBEESJOGPͷ಺෦࣮૷ 3VCZ࣌఺ ɾSTPDL@HFUBEESJOGPɹ QUISFBE͕͋Δ؀ڥ  ɹ ➡︎ EP@QUISFBE@DSFBUFɹεϨουΛੜ੒ ɹɹ ➡︎

     ࢠεϨου EP@HFUBEESJOGPɹHFUBEESJOGP  Λ࣮ߦ ɹɹɹ໊લղܾ͕ऴΘΓ࣍ୈɺ৚݅ม਺ʹ௨஌͢Δ ɹ ➡︎ SC@UISFBE@DBMM@XJUIPVU@HWM ɹɹ ➡︎ XBJU@HFUBEESJOGPɹ৚݅ม਺΁ͷ௨஌Λ଴ػ ɹɹ ➡︎ DBODFM@HFUBEESJOGPɹதஅ࣌ʹ৚݅ม਺ʹ௨஌͢Δɹ ϝΠϯεϨουͰ͸৚݅ม਺ʹ௨஌͕͋Δ·Ͱ଴ػ͢Δ ໊લղܾ͕׬ྃͰ͖͔ͨதஅ͞Ε͔ͨʹΑͬͯޙଓͷॲཧΛߦ͏
  19. 5$14PDLFUOFXͷ಺෦࣮૷ 3VCZ࣌఺ ▫5$14PDLFUOFXͷίʔϧελοΫ ɾUDQ@JOJU ɹ ➡︎ STPDL@JOJU@JOFUTPDL ɹɹ ➡︎ JOJU@JOFUTPDL@JOUFSOBM

    ɹɹɹ ➡︎ STPDL@BEESJOGPɹ໊લղܾͷ։࢝ ɹɹɹɹ ➡︎ STPDL@HFUBEESJOGP ɹɹɹɹɹ ➡︎ ҎԼಉ͡ ɹɹɹ ➡︎ ޙଓॲཧ தஅՄೳͳHFUBEESJOGPͷݺͼग़͠ STPDL@HFUBEESJOGP͸)&Wͷ࣮૷ʹར༻͞ΕΔ͜ͱΛ ૝ఆͨ͠࢓༷ʹͳ͍ͬͯͳ͍
  20. 5$14PDLFUOFXͷ಺෦࣮૷ )&WରԠ ɾUDQ@JOJU ɹ ➡︎ STPDL@JOJU@JOFUTPDL ɹɹ ➡︎ JOJU@JOFUTPDL@JOUFSOBM@IBQQZ QUISFBE͕͋Δ؀ڥ

     ɹɹɹ ➡︎ EP@QUISFBE@DSFBUFεϨουΛੜ੒ ɹɹɹɹ ➡︎ EP@SC@HFUBEESJOGP@IBQQZεϨου಺Ͱ໊લղܾΛ࣮ߦ ɹɹɹɹɹ໊લղܾ͕ऴΘΓ࣍ୈɺQJQFʹ௨஌͢Δ ɹɹɹ ➡︎ SC@UISFBE@DBMM@XJUIPVU@HWM ɹɹɹɹ ➡︎ XBJU@IBQQZ@FZFCBMMT@GETQJQF΁ͷ௨஌ΛTFMFDU  Ͱ଴ػ ɹɹɹɹ ➡︎ DBODFM@IBQQZ@FZFCBMMT@GETதஅ࣌ʹQJQF΁௨஌ ɹɹɹ ➡︎ ʜ جຊతͳίϯηϓτ͸4PDLFUUDQͱಉ͡
  21. EP@SC@HFUBEESJOGP@IBQQZ void * do_rb_getaddrinfo_happy(void *ptr) { // Ҿ਺Ͱ౉ͨ͠ϦιʔεΛ΋ͱʹgetaddrinfo(3)Λ࣮ߦ rb_nativethread_lock_lock(shared->lock); {

    // ໊લղܾ͕׬ྃͨ͠৔߹ɿpipeͷॻ͖ࠐΈଆʹͦͷࢫΛ௨஌ // தஅ͞Εͨ৔߹ɿ໊લղܾࡁΈͷ৔߹͸freeaddrinfo(3) } rb_nativethread_lock_unlock(shared->lock); // ͜ͷεϨουݻ༗ͷϦιʔεΛղ์ // Մೳͳ৔߹͸શͯͷεϨουͰڞ༗͍ͯ͠ΔϦιʔεΛղ์ return 0; } 4PDLFUUDQͱಉ͡ ޙॲཧ $࣮૷ݻ༗
  22. )&WରԠ5$14PDLFUOFXʹ͓͚ΔϦιʔεͷ҆શͳղ์ Bݻ༗ͷϦιʔε  ɾΞυϨεϑΝϛϦ ɾTUSVDUBEESJOGP ɾڞ༗Ϧιʔε΁ͷࢀর Cݻ༗ͷϦιʔε  ɾΞυϨεϑΝϛϦ ɾTUSVDUBEESJOGP

    ɾڞ༗Ϧιʔε΁ͷࢀর ໊લղܾ༻ εϨουB ໊લղܾ༻ εϨουC Bऴྃ࣌ʹղ์ Cऴྃ࣌ʹղ์ ϝΠϯεϨου
  23. ݱࡏͷ࣮૷ͷ໰୊఺ɿ۩ମྫᶃ ▫ݱঢ়ͷ࣮૷ ঢ়ଶʮWXʯʹ͍ͭͯ TFMFDU  Ͱ઀ଓ໊͔લղܾΛಉ࣌ʹ଴ػ͓ͯ͠Γ ൃੜͨ͠ΠϕϯτͱϦιʔεͷঢ়ଶʹΑͬͯ ࣍ͷঢ়ଶΛܾఆ͠ɺ࣍ͷϧʔϓʹભҠ͍ͯ͠Δ ▫໰୊఺ TFMFDU

     ͸ෳ਺ͷΠϕϯτΛಉ࣌ʹฦ͢Մೳੑ͕͋Δ FH઀ଓͱ໊લղܾͷ׬ྃΛಉ࣌ʹݕ஌͢Δ ➡︎  ঢ়گʹΑͬͯ͸ ༨ܭͳTFMFDU  ͷݺͼग़͕͠ൃੜ͢Δ
  24. 4PDLFUUDQվળͷશମ૾ Πϝʔδ def self.tcp(host, port, ...) loop do end end

    # ໊લղܾͷ։࢝ # IO.select(<໊લղܾ>, <઀ଓ>, nil, <λΠϜΞ΢τ஋>) # if ॻ͖ࠐΈՄೳͳIO͕ฦ͖ͬͯͨ then ઀ଓ֬ೝɹ(੒ޭ͍ͯͨ͠Βreturn) # if ಡΈࠐΈՄೳͳIO͕ฦ͖ͬͯͨ then ղܾࡁΈͷIPΞυϨεΛอଘ # if ઀ଓ։࢝ͷ৚݅Λຬ͍ͨͯ͠Δ then ઀ଓΛ։࢝ # unless ࣍ͷϧʔϓʹೖΔ͜ͱ͕Ͱ͖Δ then ྫ֎Λൃੜͤ͞Δ ঢ়ଶͷ؅ཧΛ΍Ίͨ͜ͱͰɺ վળલ͸DBTF͝ͱʹ࣮ߦ͍ͯͨ͠ॲཧ͕ ϧʔϓͷ্͔Βॱʹ৚݅ʹԠ࣮ͯ͡ߦ͞ΕΔΑ͏ʹͳͬͨ
  25. 4PDLFUUDQվળલͱͷൺֱɿ*0TFMFDU ▫มߋલ ɾঢ়ଶʹԠͯ͡ෳ਺ՕॴͰݺͼग़͢ ɹɹ  ։࢝௚ޙʹ໊લղܾΛ ɹɹ଴ػ͢ΔՕॴ TUBSU  ɹɹ

     *1Wͷ໊લղܾΛ ɹɹ଴ػ͢ΔՕॴ WX  ɹɹ  ઀ଓ͔ೋͭ໨ͷ໊લղܾΛ ɹɹ଴ػ͢ΔՕॴ WX  ɾλΠϜΞ΢τ஋͸ɺ ɹঢ়ଶʹԠͯࣗ͡ಈతʹܾఆ͢Δ ▫มߋޙ ɾϧʔϓͷதͷҰՕॴͷΈͰݺͼग़͢ ɾλΠϜΞ΢τ஋͸ɺ ɹͦͷ࣌఺ͰͷϦιʔεͷঢ়گ΍ɺ ɹશମͷॲཧ͕Ͳ͜·ͰਐΜͰ͍Δ͔ ɹͳͲʹΑͬͯಈతʹ൑அͨ͠஋ ends_at = if resolved_addrinfos.any? resolv_delay_expires_at || connect_delay_expires_at else [user_resolv_timeout_at, user_connect_timeout_at].compact.max end
  26. 4PDLFUUDQվળલͱͷൺֱɿ઀ଓͷ։࢝ͷ൑அ ▫มߋલ ɾ઀ଓΛ։࢝Ͱ͖Δ͔Ͳ͏͔Λ ɹݱࡏͷঢ়ଶͰ൑அ͢Δ ɹ WDɺWDɺWD  ɹ˞ݱࡏͷঢ়ଶ͸ɺ ɹɹʮҰͭલʹͲͷঢ়ଶͩͬͨͷ͔ʯͱ ɹɹʮͦͷঢ়ଶΛ཭ΕΔͱ͖ʹભҠઌ͕

    ɹɹͲͷঢ়ଶʹͳΔͷ͔ʯʹґଘ͢Δ ▫มߋޙ ɾ઀ଓΛ։࢝Ͱ͖Δ͔Ͳ͏͔Λ ɹͦͷ࣌఺ͰͷϦιʔεͷঢ়گ΍ɺ ɹશମͷॲཧ͕Ͳ͜·ͰਐΜͰ͍Δ͔ɺ ɹͳͲʹΑͬͯ൑அ͢Δ if resolved_addrinfos.any? && !resolv_delay_expires_at && !connect_delay_expires_at while (addrinfo = resolved_addrinfos.get) # ... end end
  27. 4PDLFUUDQվળલͱͷൺֱɿྫ֎ͷൃੜ ▫มߋલ ɾʮ͢΂ͯͷ໊લղܾ΍઀ଓʹ ɹɹࣦഊͨ͠ʯͱ൑அͨ͠৔߹ɺ ɹࣦഊΛද͢ঢ়ଶ GBJMVSF ʹભҠ͠ ɹͦ͜Ͱྫ֎Λൃੜͤ͞Δ ▫มߋޙ ɾϧʔϓͷऴΘΓʹࢸͬͨ࣌఺Ͱ

    ɹ΍Γ࢒ͨ͠ॲཧ΍ ɹ·ͩଓ͍͍ͯΔॲཧ͕ͳ͍͔Λ൑அ͠ɺ ɹ͜ΕҎ্Ͱ͖Δॲཧ͕ͳ͚Ε͹ ɹྫ֎Λൃੜͤ͞Δ if resolved_addrinfos.empty? if connecting_sockets.keys.empty? && resolved_addrinfos.resolved_all? raise last_error end # ... end