Share
Embed
たのしいSocketのしくみ / Socket Under a Microscope
TokyoWomen.rb #1 招待講演
https://tokyowomenrb.connpass.com/event/342573/
Misaki Shioi(塩井美咲/しおい)
March 01, 2025
Transcript
205 slides
-
QQTFMG ɹԘҪඒ࡙ ͓͍͠ ɹҬ3VCZίϛϡχςΟ"TBLVTBSC ɹ3VCZίϛολʔ ɹલΠϕϯτ5PLZP(JSMTSC.FFUVQWPMʹొஃͯ͠·ͨ͠ !TIJPJNN
(JU)VC !DPF@ FY5XJUUFS !DPF #MVFTLZ 3BDLϛυϧΣΞೖͷͨΊͷ3BDLϛυϧΣΞ IUUQTTQFBLFSEFDLDPNDPF@SBDLNJEPSVVFBSVNFOGBMTFUBNFGBMTFSBDLNJEPSVVFB -
5PLZP8PNFOSCλΠϜςʔϒϧ ਪ͠ϝιουsource_locationͷ͘͠ΈΛ୳Δ - ͡ΊͯRubyͷίʔυΛಡΜͰΈͨ ਪ͠ϝιουTPVSDF@MPDBUJPOͷ͘͠ΈΛ୳Δ ͡Ίͯ3VCZͷίʔυΛಡΜͰΈͨ ͨͷ͍͠4PDLFUͷ͘͠Έ 4PDLFUT6OEFSB.JDSPTDPQF 3BJMTͷίʔυͰֶͿ ͱͷΈ
͘͠Έ͕ؾʹͳΔਓʑ find_by_* method_missing nobu09 OPCV ͓͍͠ NBJNV IUUQTUPLZPXPNFOSCDPOOQBTTDPNFWFOU -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό 4PDLFUUDQ@TFSWFS@MPPQϝιου TPDLFUϥΠϒϥϦΛSFRVJSF -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό ࣗͷϗετ໊MPDBMIPTU αʔόࣗͷϙʔτ൪߸ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό αʔόͱͯ͠ߦ͏ॲཧ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό 4PDLFUΦϒδΣΫτ 4PDLFUΦϒδΣΫτ ιέοτΛ3VCZͷΦϒδΣΫτͰϥοϓ͠ɺ ɹ3VCZ͔Βѻ͑ΔΑ͏ʹͨ͠ͷ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό 4PDLFUΦϒδΣΫτ ͜͜ͰϒϩοΫมʹͬͯ͘Δͷɺ ϦΫΤετΛૹ৴ͨ͠ΫϥΠΞϯτͱ ଓࡁΈͷঢ়ଶͷ4PDLFUΦϒδΣΫτ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό 4PDLFUΦϒδΣΫτΛಡΈࠐΈ ΫϥΠΞϯτ͔ΒͷϦΫΤετϝοηʔδΛऔಘ ϦΫΤετΛૹ৴ͨ͠ΫϥΠΞϯτͱ ଓࡁΈͷঢ়ଶͷ4PDLFUΦϒδΣΫτ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό 4PDLFUΦϒδΣΫτʹॻ͖ࠐΈ ΫϥΠΞϯτϨεϙϯεΛૹ৴ ͜͜ͰϦΫΤετϝοηʔδΛ ͓͏Ήฦ͠ʹΫϥΠΞϯτʹૹ৴͍ͯ͠Δ ϦΫΤετΛૹ৴ͨ͠ΫϥΠΞϯτͱ ଓࡁΈͷঢ়ଶͷ4PDLFUΦϒδΣΫτ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό Ұ௨ΓΫϥΠΞϯτʹର͢Δૢ࡞͕ऴΘͬͨΒ ଓࡁΈ4PDLFUΦϒδΣΫτͷೖग़ྗΛΫϩʔζ ϦΫΤετΛૹ৴ͨ͠ΫϥΠΞϯτͱ ଓࡁΈͷঢ়ଶͷ4PDLFUΦϒδΣΫτ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό ϦΫΤετΛड͚ͯϨεϙϯεΛฦ͢ɺͱ͍͏Ұ࿈ͷྲྀΕΛϧʔϓ -
αʔόϓϩάϥϜ require "socket" Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end αʔό ΫϥΠΞϯτ͔ΒϦΫΤετΛड৴͠ɺ ͦΕΛͦͷ··ΫϥΠΞϯτʹϨεϙϯεͱͯ͠ ૹ৴͢Δ؆୯ͳ5$1ΤίʔαʔόϓϩάϥϜ a -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ TPDLFUϥΠϒϥϦΛSFRVJSF 4PDLFUUDQϝιου -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ Ѽઌϗετ໊MPDBMIPTU Ѽઌϙʔτ൪߸ -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ ΫϥΠΞϯτͱͯ͠ߦ͏ॲཧ -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ ѼઌͷαʔόͱଓࡁΈͷঢ়ଶͷ 4PDLFUΦϒδΣΫτ -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ 4PDLFUΦϒδΣΫτʹॻ͖ࠐΈ αʔόϦΫΤετϝοηʔδΛૹ৴ ѼઌͷαʔόͱଓࡁΈͷঢ়ଶͷ 4PDLFUΦϒδΣΫτ -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ 4PDLFUΦϒδΣΫτΛಡΈࠐΈ αʔό͔ΒϨεϙϯεϝοηʔδΛऔಘ ϨεϙϯεϝοηʔδΛඪ४ग़ྗ ѼઌͷαʔόͱଓࡁΈͷঢ়ଶͷ 4PDLFUΦϒδΣΫτ -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ ॲཧ͕ऴΘΔͱ4PDLFUΦϒδΣΫτࣗಈతʹΫϩʔζ ѼઌͷαʔόͱଓࡁΈͷঢ়ଶͷ 4PDLFUΦϒδΣΫτ -
ΫϥΠΞϯτϓϩάϥϜ require "socket" Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end ΫϥΠΞϯτ αʔόʹϦΫΤετ )J Λૹ৴͠ɺ αʔό͔Βड৴ͨ͠ϨεϙϯεΛͦͷ··ग़ྗ͢Δ ؆୯ͳ5$1ΫϥΠΞϯτϓϩάϥϜ a -
4PDLFUUDQ@TFSWFS@MPPQ4PDLFUUDQͷߏ Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial 100 sock.write
message ensure sock.close end Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message = sock.read puts message end αʔό ΫϥΠΞϯτ ΫϥΠΞϯτͱͷଓޙʹߦ͏ࣄ αʔόͱͷଓޙʹߦ͏ࣄ αʔόʵΫϥΠΞϯτؒͷଓཱ͕֬ͨ͠ޙʹߦ͏ॲཧΛ ֤ϝιουͷϒϩοΫʹهड़͍ͯ͠Δ -
Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial 100 sock.write message
ensure sock.close end Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message = sock.read puts message end αʔό ΫϥΠΞϯτ ωοτϫʔΫΛհ͓ͯ͠ޓ͍ʹଓཱ͕֬͢Δ·Ͱͷॲཧ ͦΕͧΕͷϝιου͕ࣗߦͳ͍ͬͯΔ 4PDLFUUDQ@TFSWFS@MPPQ4PDLFUUDQͷߏ ΫϥΠΞϯτͱͷଓ αʔόͱͷଓ -
Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial 100 sock.write message
ensure sock.close end Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message = sock.read puts message end αʔό ΫϥΠΞϯτ ͦͷཪଆͰ3VCZͲͷΑ͏ʹιέοτΛѻ͍ɺଓ͍ͯ͠Δ 4PDLFUUDQ@TFSWFS@MPPQ4PDLFUUDQͷߏ Ͳ͏ͬͯΫϥΠΞϯτͱଓ͍ͯ͠Δ Ͳ͏ͬͯαʔόͱଓ͍ͯ͠Δ -
4PDLFUUDQ ΫϥΠΞϯτ ฤ Socket.tcp("localhost", 4567) do |sock| sock.write "Hi" message
= sock.read puts message end -
4PDLFUUDQ class Socket # ... def self.tcp(host, port, ... fast_fallback:
tcp_fast_fallback, &) # ... end # ... end 4PDLFUUDQ4PDLFUΫϥεʹ Ϋϥεϝιουͱ࣮ͯ͠͞Ε͍ͯΔ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ class Socket # ... def self.tcp(host, port, ... fast_fallback:
tcp_fast_fallback, &) sock = if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, ...) else tcp_without_fast_fallback(host, port, ...) end # ... end # ... end FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ class Socket # ... def self.tcp(host, port, ... fast_fallback:
tcp_fast_fallback, &) sock = if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, ...) else tcp_without_fast_fallback(host, port, ...) end # ... end # ... end FYUTPDLFUMJCTPDLFUSC ಛఆͷ݅Ͱذ ίʔυϦʔσΟϯάͷ༰қ͔͞Βɺ ࠓճͪ͜ΒΛಡΈ·͢ -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... end FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... end FYUTPDLFUMJCTPDLFUSC "EESJOGPGPSFBDI -
"EESJOGPGPSFBDI FYUTPDLFUMJCTPDLFUSC class Addrinfo # ... def self.foreach(nodename, service, ...,
&block) Addrinfo.getaddrinfo(nodename, service, ...).each(&block) end # ... end -
class Addrinfo # ... def self.foreach(nodename, service, ..., &block) Addrinfo.getaddrinfo(nodename,
service, ...).each(&block) end # ... end "EESJOGPGPSFBDI "EESJOGPHFUBEESJOGP FYUTPDLFUMJCTPDLFUSC -
"EESJOGPHFUBEESJOGP "EESJOGPHFUBEESJOGP ͞Εͨϗετ໊ͱϙʔτ൪߸Λ*1ΞυϨεʹղܾ͠ɺ ͦͷ݁ՌҰཡΛ"EESJOGPΦϒδΣΫτͷྻͰฦ͢ϝιου (ྫ) Addrinfo.getaddrinfo("localhost", 4567, nil, :STREAM) =>
[#<Addrinfo: 127.0.0.1 TCP (localhost)>, #<Addrinfo: ::1 TCP (localhost)>] ϗετ͕*1W*1W྆ํʹରԠ͍ͯ͠Δ߹ɺฦΓʹ ͦͷ྆ํͷΞυϨεΛද͢"EESJOGPΦϒδΣΫτؚ͕·ΕΔ ϗετ໊ ϙʔτ൪߸ ໊લղܾͷώϯτ ղܾͰ͖ͨ*1ΞυϨεҰཡ -
"EESJOGPΦϒδΣΫτ "EESJOGPΦϒδΣΫτ*1ΞυϨεใΛද͢ΦϒδΣΫτ (ྫ) addrinfo # => #<Addrinfo: 127.0.0.1 TCP (localhost)>
addrinfo.ip_address # => "127.0.0.1" addrinfo.ipv4? # => true addrinfo.pfamily # => addrinfo.socktype # => "EESJOGPΦϒδΣΫτʹΞΫηε͢Δ͜ͱͰ ΞυϨεʹؔ͢ΔใΛऔಘͨ͠Γૢ࡞͢Δ͜ͱ͕Ͱ͖Δ ΞυϨεϑΝϛϦ (IPv6 / IPv4) Λද͢ ௨৴ͷछྨ (ετϦʔϜ / σʔλάϥϜ) Λද͢ -
class Addrinfo # ... def self.foreach(nodename, service, ..., &block) Addrinfo.getaddrinfo(nodename,
service, ...).each(&block) end # ... end "EESJOGPGPSFBDI ྫɿ*1Wͱ*1W྆ํʹରԠ͍ͯ͠ΔϗετͰ ɹɹϗετ໊ͱͯ͠MPDBMIPTUΛͨ͠߹ "EESJOGPHFUBEESJOGPϗετ໊Λ໊લղܾ͠ɺ *1WΞυϨεͱ*1WΞυϨεΛͦΕͧΕද͢ "EESJOGPΦϒδΣΫτΛཁૉʹ࣋ͭྻΛฦ͢ => [#<Addrinfo: 127.0.0.1 TCP (localhost)>, #<Addrinfo: ::1 TCP (localhost)>] "localhost" FYUTPDLFUMJCTPDLFUSC -
class Addrinfo # ... def self.foreach(nodename, service, ..., &block) Addrinfo.getaddrinfo(nodename,
service, ...).each(&block) end # ... end "EESJOGPGPSFBDI "EESJOGPGPSFBDI͜ͷྻʹରͯ͠FBDIΛݺͼग़͠ɺ ֤"EESJOGPΦϒδΣΫτ͝ͱʹϒϩοΫΛ࣮ߦ͢Δ "EESJOGPΦϒδΣΫτͷྻʹର͢Δ "SSBZFBDI FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... end ϒϩοΫมʹ͞ΕΔ"EESJOGPΦϒδΣΫτΛ༻͍ͯ ϒϩοΫͷॲཧΛ࣮ߦ͢Δ "EESJOGPΦϒδΣΫτ FYUTPDLFUMJCTPDLFUSC ࠶ͼ "EESJOGPGPSFBDI͕࣮ߦ͢ΔϒϩοΫ -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... end FYUTPDLFUMJCTPDLFUSC "EESJOGPDPOOFDU -
"EESJOGPDPOOFDU class Addrinfo # ... def connect(...) connect_internal(nil, ...) end
# ... end FYUTPDLFUMJCTPDLFUSC -
"EESJOGPDPOOFDU class Addrinfo # ... def connect(...) connect_internal(nil, ...) end
# ... end "EESJOGPDPOOFDU@JOUFUOBM FYUTPDLFUMJCTPDLFUSC -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC 4PDLFUOFX -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC 4PDLFUOFX ϗετ෦Ͱ৽͍͠ιέοτΛ࡞͠ɺ ɹͦΕΛ4PDLFUΦϒδΣΫτͱͯ͠ ɹѻ͑ΔΑ͏ʹͯ͠ฦ͢ -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC 4PDLFUOFX ➡︎ ͦͷ࣮ଶ$ݴޠͰ࣮ 3VCZͷ͞ΒͳΔଆΛ ͷ͍͍͖ͧͯ·͠ΐ͏ ϗετ෦Ͱ৽͍͠ιέοτΛ࡞͠ɺ ɹͦΕΛ4PDLFUΦϒδΣΫτͱͯ͠ ɹѻ͑ΔΑ͏ʹͯ͠ฦ͢ -
4PDLFUJOJUJBMJ[F void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... rb_define_method(rb_cSocket, "initialize", sock_initialize, -1); // ... } FYUTPDLFUTPDLFUD -
4PDLFUJOJUJBMJ[F void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... rb_define_method(rb_cSocket, "initialize", sock_initialize, -1); // ... } 3VCZͷ$"1*Λͬͯ 4PDLFUΫϥεͱ4PDLFUJOJUJBMJ[F͕ఆٛ͞Ε͍ͯΔ FYUTPDLFUTPDLFUD 4PDLFUΫϥεΛఆٛ 4PDLFUJOJUJBMJ[FΛఆٛ -
4PDLFUJOJUJBMJ[F void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... rb_define_method(rb_cSocket, "initialize", sock_initialize, -1); // ... } FYUTPDLFUTPDLFUD 4PDLFUJOJUJBMJ[Fͷ෦࣮ 4PDLFUJOJUJBMJ[F ࣮ମͱͯ͠TPDL@JOJUJBMJ[Fؔʹ࣮͞Ε͍ͯΔ -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } FYUTPDLFUTPDLFUD -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } ϝιουͷҾͷॲཧ FYUTPDLFUTPDLFUD -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } STPDL@TPDLFUؔ FYUTPDLFUTPDLFUD -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } STPDL@TPDLFUؔ෦Ͱ STPDL@TPDLFUؔΛݺΜͰ͍Δ FYUTPDLFUTPDLFUD -
STPDL@TPDLFU static int rsock_socket0(int domain, int type, int proto) {
// ... int result = socket(domain, type, proto); if (result == -1) return -1; rb_fd_fix_cloexec(result); #ifndef SOCK_NONBLOCK rsock_make_fd_nonblock(result); #endif return result; } FYUTPDLFUJOJUD -
STPDL@TPDLFU static int rsock_socket0(int domain, int type, int proto) {
// ... int result = socket(domain, type, proto); if (result == -1) return -1; rb_fd_fix_cloexec(result); #ifndef SOCK_NONBLOCK rsock_make_fd_nonblock(result); #endif return result; } TPDLFU γεςϜίʔϧ STPDL@TPDLFUؔͰ TPDLFUͱ͍͏γεςϜίʔϧΛݺΜͰ͍Δ aॏཁ FYUTPDLFUJOJUD -
STPDL@TPDLFU static int rsock_socket0(int domain, int type, int proto) {
// ... int result = socket(domain, type, proto); if (result == -1) return -1; rb_fd_fix_cloexec(result); #ifndef SOCK_NONBLOCK rsock_make_fd_nonblock(result); #endif return result; } ͜ͷϗετʹιέοτΛ࡞͢ΔΑ͏ Χʔωϧʹର໋ͯ͠ྩ͢Δ STPDL@TPDLFUؔ෦తʹTPDLFUΛݺͼग़͢͜ͱͰ ࣮ࡍʹϗετʹιέοτΛ࡞͍ͯ͠Δ FYUTPDLFUJOJUD TPDLFU γεςϜίʔϧ ϗετ ιέοτ -
STPDL@TPDLFU static int rsock_socket0(int domain, int type, int proto) {
// ... int result = socket(domain, type, proto); if (result == -1) return -1; rb_fd_fix_cloexec(result); #ifndef SOCK_NONBLOCK rsock_make_fd_nonblock(result); #endif return result; } TPDLFUγεςϜίʔϧɺ৽͘͠࡞ͨ͠ιέοτΛ ಛఆ͢ΔͨΊͷ൪߸ιέοτσΟεΫϦϓλΛฦ͢ ιέοτσΟεΫϦϓλΛऔಘ FYUTPDLFUJOJUD TPDLFU γεςϜίʔϧ -
STPDL@TPDLFU static int rsock_socket0(int domain, int type, int proto) {
// ... int result = socket(domain, type, proto); if (result == -1) return -1; rb_fd_fix_cloexec(result); #ifndef SOCK_NONBLOCK rsock_make_fd_nonblock(result); #endif return result; } औಘͨ͠ιέοτσΟεΫϦϓλΛฦͯ͠ऴྃ FYUTPDLFUJOJUD STPDL@TPDLFU৽͘͠࡞ͨ͠ιέοτͷ ιέοτσΟεΫϦϓλΛฦͯ͠ऴྃ͢Δ ιέοτσΟεΫϦϓλΛऔಘ TPDLFU γεςϜίʔϧ -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } FYUTPDLFUTPDLFUD ࠶ͼ STPDL@TPDLFUؔ ৽͍͠ιέοτΛ࡞ͯ͠ ιέοτσΟεΫϦϓλΛฦ͢ ෦ͰSTPDL@TPDLFUؔΛݺͿ -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } STPDL@TPDLFUؔ FYUTPDLFUTPDLFUD STPDL@TPDLFUؔͷฦΓ ৽͘͠࡞ͨ͠ιέοτͷ ιέοτσΟεΫϦϓλ ΛมGEʹ֨ೲ ࠶ͼ ৽͍͠ιέοτΛ࡞ͯ͠ ιέοτσΟεΫϦϓλΛฦ͢ ෦ͰSTPDL@TPDLFUؔΛݺͿ -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } STPDL@JOJU@TPDLؔ FYUTPDLFUTPDLFUD STPDL@JOJU@TPDLؔมGEͷιέοτσΟεΫϦϓλΛ σʔλͱͯ͠อ࣋͢Δ4PDLFUΦϒδΣΫτΛ৽ͨʹ࡞͢Δ -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } ฦΓΛSFUVSO ࠷ޙʹɺTPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[F ࡞ͨ͠4PDLFUΦϒδΣΫτΛฦͯ͠ऴྃ FYUTPDLFUTPDLFUD -
TPDL@JOJUJBMJ[F 4PDLFUJOJUJBMJ[Fͷ࣮ମ static VALUE sock_initialize(int argc, VALUE *argv, VALUE sock)
{ VALUE domain, type, protocol; int fd; int d, t; rb_scan_args(argc, argv, "21", &domain, &type, &protocol); // ... fd = rsock_socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); return rsock_init_sock(sock, fd); } 4PDLFUOFXͷ෦࣮͜͜·Ͱ FYUTPDLFUTPDLFUD -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC 4PDLFUOFX ࠶ͼ ϗετ෦Ͱ৽͍͠ιέοτΛ࡞͠ɺ ɹ͜ΕΛϥοϓ͢Δ4PDLFUΦϒδΣΫτΛฦ͢ -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC ࡞ͨ͠4PDLFUΦϒδΣΫτΛมTPDLʹ֨ೲ มTPDLʹରͯ͠4PDLFUDPOOFDU TFMGѼઌͷΞυϨεใ "EESJOGPΦϒδΣΫτ -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC 4PDLFUDPOOFDU$Ͱ࣮͞Ε͍ͯΔ ࡞ͨ͠4PDLFUΦϒδΣΫτΛมTPDLʹอଘ TFMGѼઌͷΞυϨεใ "EESJOGPΦϒδΣΫτ มTPDLʹରͯ͠4PDLFUDPOOFDU -
4PDLFUDPOOFDU void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... rb_define_method(rb_cSocket, "initialize", sock_initialize, -1); rb_define_method(rb_cSocket, "connect", sock_connect, 1); // ... } FYUTPDLFUTPDLFUD 4PDLFUDPOOFDUΛఆٛ 4PDLFUΫϥεΛఆٛ 4PDLFUDPOOFDUͷ෦࣮ 4PDLFUDPOOFDU ࣮ମͱͯ͠TPDL@DPOOFDUؔʹ࣮͞Ε͍ͯΔ -
static VALUE sock_connect(VALUE self, VALUE addr) { // ... int
result = rsock_connect( self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT ); // ... return INT2FIX(result); } TPDL@DPOOFDU 4PDLFUDPOOFDUͷ࣮ମ FYUTPDLFUTPDLFUD -
static VALUE sock_connect(VALUE self, VALUE addr) { // ... int
result = rsock_connect( self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT ); // ... return INT2FIX(result); } TPDL@DPOOFDU 4PDLFUDPOOFDUͷ࣮ମ sock.connect(self) 4PDLFUDPOOFDUͷϨγʔό 4PDLFUΦϒδΣΫτ FYUTPDLFUTPDLFUD -
static VALUE sock_connect(VALUE self, VALUE addr) { // ... int
result = rsock_connect( self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT ); // ... return INT2FIX(result); } TPDL@DPOOFDU 4PDLFUDPOOFDUͷ࣮ମ sock.connect(self) ѼઌͷΞυϨεใΛอ࣋͢Δ 4PDLFUDPOOFDUͷҾ "EESJOGPΦϒδΣΫτ FYUTPDLFUTPDLFUD -
static VALUE sock_connect(VALUE self, VALUE addr) { // ... int
result = rsock_connect( self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT ); // ... return INT2FIX(result); } TPDL@DPOOFDU 4PDLFUDPOOFDUͷ࣮ମ STPDL@DPOOFDUؔ FYUTPDLFUTPDLFUD Ϩγʔόͷ4PDLFUΦϒδΣΫτ ҾͰड͚औͬͨѼઌͷΞυϨεใ sock.connect(self) -
TPDL@DPOOFDU 4PDLFUDPOOFDUͷ࣮ମ static VALUE sock_connect(VALUE self, VALUE addr) { //
... int result = rsock_connect( self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT ); // ... return INT2FIX(result); } STPDL@DPOOFDUؔ෦Ͱ DPOOFDU@CMPDLJOHؔΛݺΜͰ͍Δ FYUTPDLFUTPDLFUD -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } FYUTPDLFUJOJUD -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } FYUTPDLFUJOJUD ҾEBUB DPOOFDU@CMPDLJOHؔҾEBUBΛհͯ͠ STPDL@DPOOFDUؔʹͨ͠ҾͷதΛड͚औΔ ɾϨγʔόͷ4PDLFUΦϒδΣΫτ͔Β औΓग़ͨ͠෦ใ ɾѼઌͷΞυϨεใ ʜΛؚΉ -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } FYUTPDLFUJOJUD ҾEBUBͷதΛมBSHʹ֨ೲ -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } DPOOFDU@CMPDLJOHؔͰ γεςϜίʔϧDPOOFDUΛݺͿ aॏཁ DPOOFDU γεςϜίʔϧ ࢦఆͷιέοτΛͬͯѼઌͱͷଓΛ։࢝͢Δ FYUTPDLFUJOJUD ΫϥΠΞϯτ ଓΛ։࢝ Ѽઌ ྫ -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } มBSH͔ΒιέοτσΟεΫϦϓλΛऔΓग़͠ɺ DPOOFDUͷୈҰҾʹ͢ɻ ͜ΕʹΑΓʮͲͷιέοτΛ͏͔ʯΛࢦఆ͍ͯ͠Δ FYUTPDLFUJOJUD มBSH͔ΒऔΓग़ͨ͠ιέοτσΟεΫϦϓλ -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } มBSH͔ΒऔΓग़ͨ͠ଓઌͷΞυϨεใ มBSH͔ΒѼઌͷΞυϨεใΛऔΓग़͠ɺ DPOOFDUͷୈೋҾʹ͢ɻ ͜ΕʹΑΓʮͲ͜Ѽʹଓ͢Δ͔ʯΛࢦఆ͍ͯ͠Δ FYUTPDLFUJOJUD -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } ଓʹޭ͢ΔͱDPOOFDUػΛղআ͠ ֘ιέοτѼઌϗετͱଓࡁΈͷঢ়ଶʹͳΔ FYUTPDLFUJOJUD ଓࢼߦ։࢝ޙɺଓঢ়ଶ͕֬ఆ͢Δ·Ͱػ͢Δ ˞֘ιέοτ͕ϊϯϒϩοΩϯάϞʔυʹઃఆ͞Ε͍ͯͳ͍߹ ˞ ΫϥΠΞϯτ αʔό aaଓཱ֬ -
DPOOFDU@CMPDLJOH static VALUE connect_blocking(void *data) { struct connect_arg *arg =
data; return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); } 4PDLFUDPOOFDUͷ෦࣮͜͜·Ͱ FYUTPDLFUJOJUD -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end FYUTPDLFUMJCTPDLFUSC ࠶ͼ 4PDLFUDPOOFDU ࢦఆͷιέοτΛͬͯѼઌʹଓΛ։࢝͢Δ -
"EESJOGPDPOOFDU@JOUFSOBM class Addrinfo # ... def connect_internal(...) sock = Socket.new(self.pfamily,
self.socktype, self.protocol) begin # ... sock.connect(self) rescue Exception sock.close raise end # ... sock end # ... end "EESJOGPDPOOFDU@JOUFSOBMɺѼઌϗετͱ ଓࡁΈͷ4PDLFUΦϒδΣΫτΛฦͯ͠ऴྃ αʔόͱଓࡁΈͷ4PDLFUΦϒδΣΫτΛฦ͢ FYUTPDLFUMJCTPDLFUSC 4PDLFUDPOOFDU -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... ret end FYUTPDLFUMJCTPDLFUSC ࠶ͼ "EESJOGPDPOOFDU 4PDLFUΦϒδΣΫτΛ࡞ˠଓ ෦Ͱ"EESJOGPDPOOFDU@JOUFSOBMΛݺͿ -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... ret end "EESJOGPDPOOFDUͷฦΓͱͯ͠ ଓࡁΈͷ4PDLFUΦϒδΣΫτΛมSFUʹอଘ্ͨ͠ "EESJOGPGPSFBDIͷϧʔϓΛCSFBL ଓࡁΈͷ4PDLFUΦϒδΣΫτΛ มTPDLʹอଘ มTPDLΛมSFUʹอଘͯ͠CSFBL FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL def self.tcp_without_fast_fallback(host, port, ...) # ... Addrinfo.foreach(host, port, nil,
:STREAM, ...) {|ai| # ... begin sock = ai.connect(...) rescue SystemCallError last_error = $! next end ret = sock break } # ... ret end ࠷ޙʹมSFU ଓࡁΈͷ4PDLFUΦϒδΣΫτ Λ ฦͯ͠4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDLऴྃ ฦΓ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ def self.tcp(host, port, ... fast_fallback: tcp_fast_fallback, &) sock =
if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, ...) else tcp_without_fast_fallback(host, port, ...) end if block_given? begin yield sock ensure sock.close end else sock end end FYUTPDLFUMJCTPDLFUSC ࠶ͼ 4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL ଓࡁΈͷ4PDLFUΦϒδΣΫτΛऔಘ -
4PDLFUUDQ def self.tcp(host, port, ... fast_fallback: tcp_fast_fallback, &) sock =
if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, ...) else tcp_without_fast_fallback(host, port, ...) end if block_given? begin yield sock ensure sock.close end else sock end end FYUTPDLFUMJCTPDLFUSC ฦΓͷ4PDLFUΦϒδΣΫτΛมTPDLʹ֨ೲ 4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDLͷฦΓͰ͋Δ ଓࡁΈ4PDLFUΦϒδΣΫτΛมTPDLʹอଘ 4PDLFUUDQ@XJUIPVU@GBTU@GBMMCBDL ଓࡁΈͷ4PDLFUΦϒδΣΫτΛऔಘ -
4PDLFUUDQ def self.tcp(host, port, ... fast_fallback: tcp_fast_fallback, &) sock =
if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, ...) else tcp_without_fast_fallback(host, port, ...) end if block_given? begin yield sock ensure sock.close end else sock end end ଓࡁΈͷ4PDLFUΦϒδΣΫτΛͬͯ 4PDLFUUDQͷϒϩοΫΛ࣮ߦ͢Δ FYUTPDLFUMJCTPDLFUSC Socket.tcp(...) do |sock| sock.write "Hi" message = sock.read puts message end -
4PDLFUUDQ def self.tcp(host, port, ... fast_fallback: tcp_fast_fallback, &) sock =
if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, ...) else tcp_without_fast_fallback(host, port, ...) end if block_given? begin yield sock ensure sock.close end else sock end end ଓࡁΈͷ4PDLFUΦϒδΣΫτΛͬͯ 4PDLFUUDQͷϒϩοΫΛ࣮ߦ͢Δ Socket.tcp(...) do |sock| sock.write "Hi" message = sock.read puts message end aΰʔϧ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@TFSWFS@MPPQ αʔό ฤ Socket.tcp_server_loop("localhost", 4567) do |sock| message = sock.readpartial
100 sock.write message ensure sock.close end -
4PDLFUUDQ@TFSWFS@MPPQ class Socket # ... def self.tcp_server_loop(host=nil, port, &b) tcp_server_sockets(host,
port) {|sockets| accept_loop(sockets, &b) } end # ... end FYUTPDLFUMJCTPDLFUSC -
class Socket # ... def self.tcp_server_loop(host=nil, port, &b) tcp_server_sockets(host, port)
{|sockets| accept_loop(sockets, &b) } end # ... end 4PDLFUUDQ@TFSWFS@MPPQ 4PDLFUUDQ@TFSWFS@TPDLFUT ϗετ໊ ϙʔτ൪߸ FYUTPDLFUMJCTPDLFUSC 4PDLFUUDQ@TFSWFS@TPDLFUTΛݺͼग़͢ αʔόࣗͷ -
4PDLFUUDQ@TFSWFS@TPDLFUT def self.tcp_server_sockets(host=nil, port, &b) if port == 0 sockets
= tcp_server_sockets_port0(host) else last_error = nil sockets = [] begin # ... rescue Exception sockets.each(&:close) raise end # ... end end ϗετ໊ɾϙʔτ൪߸ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@TFSWFS@TPDLFUT def self.tcp_server_sockets(host=nil, port, &b) if port == 0 sockets
= tcp_server_sockets_port0(host) else last_error = nil sockets = [] begin # ... rescue Exception sockets.each(&:close) raise end # ... end end ϙʔτ൪߸ʹΛ͍ͯ͠Δ߹ ϙʔτ൪߸ʹҎ֎Λ͍ͯ͠Δ߹ ίʔυϦʔσΟϯάͷ༰қ͔͞Βɺ ࠓճͪ͜ΒΛಡΈ·͢ ϗετ໊ɾϙʔτ൪߸ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@TFSWFS@TPDLFUT last_error = nil sockets = [] begin # ...
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end FYUTPDLFUMJCTPDLFUSC ˞if port == 0ͷelseઅͷத -
4PDLFUUDQ@TFSWFS@TPDLFUT last_error = nil sockets = [] begin # ...
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end "EESJOGPGPSFBDI FYUTPDLFUMJCTPDLFUSC ˞if port == 0ͷelseઅͷத αʔόࣗͷϗετ໊ͷ໊લղܾΛߦ͏ -
4PDLFUUDQ@TFSWFS@TPDLFUT last_error = nil sockets = [] begin # ...
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end [#<Addrinfo: 127.0.0.1 TCP (localhost)>, #<Addrinfo: ::1 TCP (localhost)>] FYUTPDLFUMJCTPDLFUSC "localhost" "EESJOGPΦϒδΣΫτ ˞if port == 0ͷelseઅͷத ˞ྫ ˞ྫ ղܾͨ͠*1ΞυϨεΛද͢"EESJOGPΦϒδΣΫτ͕ ϒϩοΫมBJʹͬͯ͘Δ -
4PDLFUUDQ@TFSWFS@TPDLFUT last_error = nil sockets = [] begin # ...
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end "EESJOGPMJTUFO FYUTPDLFUMJCTPDLFUSC ˞if port == 0ͷelseઅͷத "EESJOGPΦϒδΣΫτ -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC 4PDLFUOFX ৽͍͠4PDLFUΦϒδΣΫτΛ࡞͢Δ -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC มTPDLʹରͯ͠4PDLFUCJOE TFMGαʔόࣗͷΞυϨεใ "EESJOGPΦϒδΣΫτ ࡞ͨ͠4PDLFUΦϒδΣΫτʹରͯ͠ 4PDLFUCJOEϝιουΛݺͿ ࡞ͨ͠4PDLFUΦϒδΣΫτΛมTPDLʹ֨ೲ -
4PDLFUCJOE void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... rb_define_method(rb_cSocket, "bind", sock_bind, 1); // ... } 4PDLFUCJOE ࣮ମͱͯ͠TPDL@CJOEؔʹ࣮͞Ε͍ͯΔ FYUTPDLFUTPDLFUD 4PDLFUCJOEΛఆٛ 4PDLFUΫϥεΛఆٛ 4PDLFUCJOEͷ෦࣮ -
TPDL@CJOE 4PDLFUCJOEͷ࣮ମ static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE
rai; rb_io_t *fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } FYUTPDLFUTPDLFUD -
TPDL@CJOE 4PDLFUCJOEͷ࣮ମ static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE
rai; rb_io_t *fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } sock.bind(self) ୈҰҾʜ4PDLFUCJOEͷϨγʔό 4PDLFUΦϒδΣΫτ ୈೋҾʜ4PDLFUCJOEͷҾ "EESJOGPΦϒδΣΫτ ࣗͷΞυϨεใΛอ࣋͢Δ FYUTPDLFUTPDLFUD -
static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE rai; rb_io_t
*fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } TPDL@CJOE 4PDLFUCJOEͷ࣮ମ Ϩγʔόͷ4PDLFUΦϒδΣΫτ͔Β ෦ใΛऔಘͯ͠มGQUSʹอଘ FYUTPDLFUTPDLFUD (FU0QFO'JMFϚΫϩ -
static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE rai; rb_io_t
*fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } TPDL@CJOE 4PDLFUCJOEͷ࣮ମ TPDL@CJOEؔͰγεςϜίʔϧCJOEΛݺΜͰ͍Δ aॏཁ FYUTPDLFUTPDLFUD ࢦఆͷιέοτʹಛఆͷΞυϨεΛඥ͚ͮΔ CJOE γεςϜίʔϧ -
static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE rai; rb_io_t
*fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } TPDL@CJOE 4PDLFUCJOEͷ࣮ମ มGQUS͔ΒऔΓग़ͨ͠ιέοτσΟεΫϦϓλΛ CJOEͷୈҰҾʹ͢ɻ ͜ΕʹΑΓʮͲͷιέοτΛ͏͔ʯΛࢦఆ͍ͯ͠Δ มGQUS͔ΒऔΓग़ͨ͠ιέοτσΟεΫϦϓλ FYUTPDLFUTPDLFUD -
static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE rai; rb_io_t
*fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } TPDL@CJOE 4PDLFUCJOEͷ࣮ମ CJOEͷୈೋҾʹαʔόࣗͷΞυϨεใΛ͢ɻ ͜ΕʹΑΓʮͲͷΞυϨεΛιέοτʹඥ͚ͮΔ͔ʯΛ ࢦఆ͍ͯ͠Δ ࣗͷΞυϨεใ FYUTPDLFUTPDLFUD -
static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE rai; rb_io_t
*fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } TPDL@CJOE 4PDLFUCJOEͷ࣮ମ CJOEΛݺͼग़͢͜ͱʹΑΓɺ ʮͲͷιέοτ͕Ͳͷ*1ΞυϨεͰ ɹϦΫΤετΛػ͢Δ͔ʯΛࢦఆ͍ͯ͠Δ FYUTPDLFUTPDLFUD ϦΫΤετΛػ͢ΔΞυϨε *1ΞυϨεΛඥ͚ ྫ -
static VALUE sock_bind(VALUE sock, VALUE addr) { VALUE rai; rb_io_t
*fptr; SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) { rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); } return INT2FIX(0); } TPDL@CJOE 4PDLFUCJOEͷ࣮ମ 4PDLFUCJOEͷ෦࣮͜͜·Ͱ FYUTPDLFUTPDLFUD *1ΞυϨεΛඥ͚ -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin sock.ipv6only! if self.ipv6? # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC 4PDLFUCJOE ࢦఆͷιέοτͱࣗͷΞυϨεΛඥ͚ͮΔ ࠶ͼ -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin sock.ipv6only! if self.ipv6? # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC 4PDLFUMJTUFO -
4PDLFUMJTUFO void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... rb_define_method(rb_cSocket, "bind", sock_bind, 1); rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1); // ... } FYUTPDLFUTPDLFUD 4PDLFUΫϥεΛఆٛ 4PDLFUMJTUFO ࣮ମͱͯ͠STPDL@TPDL@MJTUFOؔʹ࣮͞Ε͍ͯΔ 4PDLFUMJTUFOΛఆٛ 4PDLFUMJTUFOͷ෦࣮ -
STPDL@TPDL@MJTUFO 4PDLFUMJTUFOͷ࣮ମ VALUE rsock_sock_listen(VALUE sock, VALUE log) { rb_io_t *fptr;
int backlog; backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); } -
STPDL@TPDL@MJTUFO 4PDLFUMJTUFOͷ࣮ମ VALUE rsock_sock_listen(VALUE sock, VALUE log) { rb_io_t *fptr;
int backlog; backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); } 4PDLFUMJTUFOͷϨγʔό 4PDLFUΦϒδΣΫτ Ϩγʔόͷ4PDLFUΦϒδΣΫτ͔Β ෦ใΛऔಘͯ͠มGQUSʹอଘ (FU0QFO'JMFϚΫϩ -
VALUE rsock_sock_listen(VALUE sock, VALUE log) { rb_io_t *fptr; int backlog;
backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); } STPDL@TPDL@MJTUFO 4PDLFUMJTUFOͷ࣮ମ STPDL@TPDL@MJTUFOؔͰ γεςϜίʔϧMJOTUFOΛݺΜͰ͍Δ aॏཁ MJTUFO γεςϜίʔϧ ࢦఆͷιέοτͰଓΛͪड͚Δ -
VALUE rsock_sock_listen(VALUE sock, VALUE log) { rb_io_t *fptr; int backlog;
backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); } STPDL@TPDL@MJTUFO 4PDLFUMJTUFOͷ࣮ମ มGQUS͔ΒऔΓग़ͨ͠ιέοτσΟεΫϦϓλ มGQUS͔ΒऔΓग़ͨ͠ιέοτσΟεΫϦϓλΛ MJTUFOͷୈҰҾʹ͢ɻ ͜ΕʹΑΓʮͲͷιέοτΛ͏͔ʯΛࢦఆ͍ͯ͠Δ -
VALUE rsock_sock_listen(VALUE sock, VALUE log) { rb_io_t *fptr; int backlog;
backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); } STPDL@TPDL@MJTUFO 4PDLFUMJTUFOͷ࣮ମ MJTUFOΛݺͼग़͢͜ͱʹΑΓɺ ࣮ࡍʹ͜ͷιέοτͰͷଓػ͕։࢝͢Δ ྫ ଓͪ -
VALUE rsock_sock_listen(VALUE sock, VALUE log) { rb_io_t *fptr; int backlog;
backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); } STPDL@TPDL@MJTUFO 4PDLFUMJTUFOͷ࣮ମ 4PDLFUMJTUFOͷ෦࣮͜͜·Ͱ ଓͪ -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin sock.ipv6only! if self.ipv6? # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC ࠶ͼ 4PDLFUMJTUFO ࢦఆͷιέοτͰଓΛػ͢Δ -
"EESJOGPMJTUFO class Addrinfo def listen(backlog=Socket::SOMAXCONN) sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin sock.ipv6only! if self.ipv6? # ... sock.bind(self) sock.listen(backlog) rescue Exception sock.close raise end # ... sock end end FYUTPDLFUMJCTPDLFUSC ଓػதͷ4PDLFUΦϒδΣΫτ 4PDLFUΦϒδΣΫτΛฦͯ͠"EESJOGPMJTUFOΛऴྃ -
4PDLFUUDQ@TFSWFS@TPDLFUT last_error = nil sockets = [] begin # ...
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end ࠶ͼ ˞if port == 0ͷelseઅͷத "EESJOGPMJTUFO ৽͘͠ιέοτΛ࡞ ɹˠࣗࣗͷΞυϨεΛඥ͚ ɹˠଓػΛ։࢝ -
4PDLFUUDQ@TFSWFS@TPDLFUT last_error = nil sockets = [] begin # ...
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end "EESJOGPMJTUFOͷฦΓͱͯ͠ ଓػΛ։࢝ͨ͠4PDLFUΦϒδΣΫτΛ ྻTPDLFUTʹ֨ೲ มTʹ֨ೲͨ͠4PDLFUΦϒδΣΫτΛྻTPDLFUTʹ֨ೲ ˞if port == 0ͷelseઅͷத "EESJOGPMJTUFO ฦΓͷ4PDLFUΦϒδΣΫτΛมTʹ֨ೲ -
last_error = nil sockets = [] begin # ... Addrinfo.foreach(host,
port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s # ... } # ... end [#<Addrinfo: 127.0.0.1 TCP (localhost)>, #<Addrinfo: ::1 TCP (localhost)>] FYUTPDLFUMJCTPDLFUSC "localhost" ͜͜·Ͱͷॲཧ ιέοτͷ࡞ɺΞυϨεͷඥ͚ɺ ଓػ։࢝ɺྻͷอଘ Λɺ໊લղܾͰऔಘͨ͠ ͯ͢ͷ"EESJOGPΦϒδΣΫτʹରͯ͠܁Γฦ͢ ˞ྫ ˞ྫ "EESJOGPMJTUFO 4PDLFUUDQ@TFSWFS@TPDLFUT -
4PDLFUUDQ@TFSWFS@TPDLFUT def self.tcp_server_sockets(host=nil, port, &b) if port == 0 sockets
= tcp_server_sockets_port0(host) else end if block_given? begin yield sockets ensure sockets.each(&:close) end else sockets end end ઌ΄Ͳ·Ͱͷॲཧ 4PDLFUUDQ@TFSWFS@TPDLFUTϝιουͷଓ͖ "EESJOGPGPSFBDI͕ऴྃͯ͠ɺ if port == 0ͷelseઅΛൈ͚ͨޙ Ҿ͖ଓ͖ ྻTPDLFUTʹଓػதͷ4PDLFUΦϒδΣΫτ͕อଘ͞Ε͍ͯΔ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@TFSWFS@TPDLFUT def self.tcp_server_sockets(host=nil, port, &b) if port == 0 sockets
= tcp_server_sockets_port0(host) else end if block_given? begin yield sockets ensure sockets.each(&:close) end else sockets end end ͜ͷϝιουͷݺͼग़࣌͠ʹ͞Ε͍ͯͨ ϒϩοΫΛ࣮ߦ͢Δ def self.tcp_server_loop(host=nil, port, &b) tcp_server_sockets(host, port) {|sockets| accept_loop(sockets, &b) } end ઌ΄Ͳ·Ͱͷॲཧ FYUTPDLFUMJCTPDLFUSC ϒϩοΫ -
4PDLFUUDQ@TFSWFS@TPDLFUT def self.tcp_server_sockets(host=nil, port, &b) if port == 0 sockets
= tcp_server_sockets_port0(host) else end if block_given? begin yield sockets ensure sockets.each(&:close) end else sockets end end def self.tcp_server_loop(host=nil, port, &b) tcp_server_sockets(host, port) {|sockets| accept_loop(sockets, &b) } end 4PDLFUBDDFQU@MPPQ ઌ΄Ͳ·Ͱͷॲཧ FYUTPDLFUMJCTPDLFUSC -
4PDLFUUDQ@TFSWFS@TPDLFUT def self.tcp_server_sockets(host=nil, port, &b) if port == 0 sockets
= tcp_server_sockets_port0(host) else end if block_given? begin yield sockets ensure sockets.each(&:close) end else sockets end end def self.tcp_server_loop(host=nil, port, &b) tcp_server_sockets(host, port) {|sockets| accept_loop(sockets, &b) } end ଓػதͷ4PDLFUΦϒδΣΫτͷྻ ઌ΄Ͳ·Ͱͷॲཧ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end ଓػதͷ4PDLFUΦϒδΣΫτͷྻ 4PDLFUBDDFQU@MPPQҾͱͯ͠ ଓػதͷ4PDLFUΦϒδΣΫτͷྻΛड͚औΔ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end ϧʔϓॲཧ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end ϧʔϓॲཧ αʔόΫϥΠΞϯτ͔ΒԿ ϦΫΤετΛड͚ΔͨΊɺ Ұ࿈ͷॲཧΛϧʔϓͯ͠ߦ͍ͬͯΔ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end *0TFMFDU TPDLFUTଓػதͷ4PDLFUΦϒδΣΫτͷྻ *0TFMFDUʹଓػதͷ4PDLFUΦϒδΣΫτͷྻΛ ͯ͠ݺͼग़͢ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end *0TFMFDU TPDLFUTଓػதͷ4PDLFUΦϒδΣΫτͷྻ *0TFMFDU Ҿʹ͍ͯ͠Δ4PDLFUΦϒδΣΫτͷ͍ͣΕ͔ʹ ϦΫΤετ͕ಧ͘·Ͱɺ͜͜ͰॲཧΛϒϩοΫ͢Δ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end *0TFMFDU TPDLFUTଓػதͷ4PDLFUΦϒδΣΫτͷྻ ͍ͣΕ͔ͷ4PDLFUΦϒδΣΫτʹϦΫΤετ͕ಧ͘ͱɺ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end *0TFMFDUͷฦΓ SFBEBCMFϦΫΤετ͕ಧ͍ͨ4PDLFUΦϒδΣΫτͷྻ *0TFMFDUػΛղআ͠ɺ ରͷ4PDLFUΦϒδΣΫτΛཁૉʹ࣋ͭ ྻSFBEBCMFΛฦ͢ FYUTPDLFUMJCTPDLFUSC -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets"
end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end 4PDLFUBDDFQU@OPOCMPDL ϦΫΤετ͕ಧ͍ͨ4PDLFUΦϒδΣΫτʹରͯ͠ ॱʹ4PDLFUBDDFQU@OPOCMPDLϝιουΛݺͼग़͢ ϦΫΤετ͕ಧ͍ͨ4PDLFUΦϒδΣΫτ FYUTPDLFUMJCTPDLFUSC -
4PDLFU@@BDDFQU@OPOCMPDL void Init_socket(void) { // ... rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
// ... /* for ext/socket/lib/socket.rb use only: */ rb_define_private_method(rb_cSocket, "__accept_nonblock", sock_accept_nonblock, 1); // ... } FYUTPDLFUTPDLFUD 4PDLFU@@BDDFQU@OPOCMPDL$Ͱ࣮͞Ε͍ͯΔ TPDLFUSCϑΝΠϧ͔Βݺͼग़ͨ͢Ί͚ͩʹ࣮͞Ε͍ͯΔ 4PDLFUΫϥεΛఆٛ 4PDLFU@@BDDFQU@OPOCMPDLΛఆٛ 4PDLFU@@BDDFQU@OPOCMPDLͷ෦࣮ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ FYUTPDLFUTPDLFUD -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ FYUTPDLFUTPDLFUD 4PDLFUBDDFQU@OPOCMPDLͷϨγʔό 4PDLFUΦϒδΣΫτ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ FYUTPDLFUTPDLFUD Ϩγʔόͷ4PDLFUΦϒδΣΫτͱผʹɺ ৽͍͠4PDLFUΦϒδΣΫτΛ֨ೲ͢ΔͨΊͷ มTPDLΛએݴ ͋ͱͰ͏ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ FYUTPDLFUTPDLFUD 4PDLFUBDDFQU@OPOCMPDLͷϨγʔό 4PDLFUΦϒδΣΫτ Ϩγʔόͷ4PDLFUΦϒδΣΫτ͔Β ෦ใΛऔಘͯ͠มGQUSʹอଘ (FU0QFO'JMFϚΫϩ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ STPDL@T@BDDFQU@OPOCMPDLؔ FYUTPDLFUTPDLFUD -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ Ϩγʔόͷ4PDLFUΦϒδΣΫτͷ෦ใ FYUTPDLFUTPDLFUD -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ STPDL@T@BDDFQU@OPOCMPDLؔ ෦ͰDMPFYFD@BDDFQUؔΛݺΜͰ͍Δ FYUTPDLFUTPDLFUD -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } FYUTPDLFUJOJUD -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } FYUTPDLFUJOJUD Ϩγʔόͷ4PDLFUΦϒδΣΫτͷιέοτσΟεΫϦϓλ -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } DMPFYFD@BDDFQUؔͰγεςϜίʔϧ BDDFQUΛݺͿ BDDFQU γεςϜίʔϧ aॏཁ FYUTPDLFUJOJUD ΫϥΠΞϯτ͔ΒͷϦΫΤετΛ ࢦఆͷιέοτͰड͚ೖΕΔ ˞JGEFG)"7&@"$$&15͕GBMTFͷ߹ -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } FYUTPDLFUJOJUD ҾʹιέοτσΟεΫϦϓλΛ͠ɺ ʮͲͷιέοτͷϦΫΤετΛड͚͚Δͷ͔ʯΛࢦఆ Ϩγʔόͷ4PDLFUΦϒδΣΫτͷιέοτσΟεΫϦϓλ -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } BDDFQU͕ϦΫΤετΛड͚͚Δͱ FYUTPDLFUJOJUD ΫϥΠΞϯτ αʔό BDDFQU -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } ϦΫΤετΛͪड͚͍ͯΔιέοτ B ͱผʹ ΫϥΠΞϯτͱଓ͞Εͨ৽͍͠ιέοτ C ͕࡞͞ΕΔ FYUTPDLFUJOJUD ΫϥΠΞϯτ aaଓཱ֬ αʔό C B -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } ΫϥΠΞϯτͱଓࡁΈͷιέοτͷ ιέοτσΟεΫϦϓλ BDDFQU৽͘͠࡞͞Εͨιέοτ C ͷ ιέοτσΟεΫϦϓλΛฦ͢ FYUTPDLFUJOJUD ΫϥΠΞϯτ αʔό C B aaଓཱ֬ -
DMPFYFD@BDDFQU static int cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{ socklen_t len0 = 0; if (address_len) len0 = *address_len; #ifdef HAVE_ACCEPT4 // ... #else int result = accept(socket, address, ...); if (result == -1) return -1; rb_maygvl_fd_fix_cloexec(result); rsock_make_fd_nonblock(result); #endif if (address_len && len0 < *address_len) *address_len = len0; return result; } DMPFYFD@BDDFQUؔ৽͘͠࡞͞Εͨιέοτ C ͷ ιέοτσΟεΫϦϓλΛฦͯ͠ऴྃ FYUTPDLFUJOJUD ΫϥΠΞϯτ αʔό C B aaଓཱ֬ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ FYUTPDLFUTPDLFUD ࠶ͼ STPDL@T@BDDFQU@OPOCMPDLؔ ෦ͰDMPFYFD@BDDFQUؔΛݺͿ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } FYUTPDLFUTPDLFUD STPDL@T@BDDFQU@OPOCMPDLؔ ৽͘͠࡞ͨ͠ૉͷιέοτΛ 4PDLFUΦϒδΣΫτʹมͯ͠ฦ͢ TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } FYUTPDLFUTPDLFUD ৽͍͠4PDLFUΦϒδΣΫτΛ֨ೲ ৽͍͠4PDLFUΦϒδΣΫτΛ֨ೲ͢ΔͨΊͷมTPDLΛએݴ TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ STPDL@T@BDDFQU@OPOCMPDLؔ ৽͘͠࡞ͨ͠ૉͷιέοτΛ 4PDLFUΦϒδΣΫτʹมͯ͠ฦ͢ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } FYUTPDLFUTPDLFUD TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ 4PDLFUΦϒδΣΫτͱଓઌΞυϨεΛද͢"EESJOGPΦϒδΣΫτΛྻʹͯ͠ฦ͢ -
static VALUE sock_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; VALUE
sock2; union_sockaddr buf; struct sockaddr *addr = &buf.addr; socklen_t len = (socklen_t)sizeof buf; GetOpenFile(sock, fptr); sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) return sock2; /* :wait_readable */ return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } FYUTPDLFUTPDLFUD TPDL@BDDFQU@OPOCMPDL 4PDLFU@@BDDFQU@OPOCMPDLͷ࣮ମ 4PDLFU@@BDDFQU@OPOCMPDLͷ෦࣮͜͜·Ͱ -
4PDLFUBDDFQU@MPPQ ࠶ͼ def self.accept_loop(*sockets) # ... loop { readable, _,
_ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end 4PDLFUBDDFQU@OPOCMPDL ଓΛड͚͚Δ -
def self.accept_loop(*sockets) # ... loop { readable, _, _ =
IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end 4PDLFUBDDFQU@MPPQ 4PDLFUBDDFQU@OPOCMPDLͷฦΓ͔Β มTPDLʹΫϥΠΞϯτͱଓࡁΈͷ ৽͍͠4PDLFUΦϒδΣΫτΛ֨ೲ 4PDLFUBDDFQU@OPOCMPDL ଓΛड͚͚Δ -
def self.accept_loop(*sockets) # ... loop { readable, _, _ =
IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end Socket.tcp_server_loop(...) do |sock| message = sock.readpartial 100 sock.write message ensure sock.close end 4PDLFUBDDFQU@MPPQ ଓࡁΈͷ4PDLFUΦϒδΣΫτΛͬͯϒϩοΫΛ࣮ߦ -
4PDLFUBDDFQU@MPPQ def self.accept_loop(*sockets) # ... loop { readable, _, _
= IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end ଓࡁΈͷ4PDLFUΦϒδΣΫτΛͬͯϒϩοΫΛ࣮ߦ aΰʔϧ Socket.tcp_server_loop(...) do |sock| message = sock.readpartial 100 sock.write message ensure sock.close end -
ιέοτ͓ͬͯ͠Ζ͍ ΫϥΠΞϯτͱαʔόɺͦΕͧΕ͕Ұ࿈ͷखଓ͖ʹԊͬͯ ιέοτ"1*Λૢ࡞͢Δ͜ͱʹΑͬͯɺ ΫϥΠΞϯτ αʔό ιέοτ ɾ ɾ ɾ ɾ
γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ ɾ ɾ γεςϜίʔϧ γεςϜίʔϧ socket connect socket bind listen accept ˞5$1ͷ߹ -
ιέοτ͓ͬͯ͠Ζ͍ ιέοτΛ௨ͯ͡ɺωοτϫʔΫͷ྆ʹ͍Δϗετಉ࢜Ͱ ίϛϡχέʔγϣϯΛऔΔ͜ͱ͕Ͱ͖Δ ΫϥΠΞϯτ αʔό Ϩεϙϯε ϦΫΤετ ɾ ɾ ɾ
ɾ γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ ɾ ɾ γεςϜίʔϧ γεςϜίʔϧ socket connect socket bind listen accept ˞5$1ͷ߹ -
4PDLFUUDQ4PDLFUUDQ@TFSWFS@MPPQͷେ෦3VCZ࣮ 3VCZ͓ͬͯ͠Ζ͍ Socket.tcp_server_loop Socket.tcp_server_sockets Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo#listen Socket.new Socket#bind Socket#listen
Socket.accept_loop Socket#accept_nonblock Socket.tcp Socket.tcp_without_fast_fallback Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo.connect Addrinfo.connect_internal Socket.new Socket#cennect ͷίʔϧελοΫ ͷίʔϧελοΫ -
4PDLFUUDQ4PDLFUUDQ@TFSWFS@MPPQͷେ෦3VCZ࣮ ͜ΕΒͷ࣮ࣗମ͕3VCZΛͬͨιέοτϓϩάϥϛϯά 3VCZ͓ͬͯ͠Ζ͍ Socket.tcp_server_loop Socket.tcp_server_sockets Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo#listen Socket.new Socket#bind
Socket#listen Socket.accept_loop Socket#accept_nonblock Socket.tcp Socket.tcp_without_fast_fallback Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo.connect Addrinfo.connect_internal Socket.new Socket#cennect ͷίʔϧελοΫ ͷίʔϧελοΫ -
͜ͷͱ͖ιέοτΛૢ࡞͢Δ෦ɺ࣮ࡍ 3VCZͷ෦Ͱ$Ͱ࣮͞Ε͍ͯΔ Socket.tcp_server_loop Socket.tcp_server_sockets Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo#listen Socket.new Socket#bind Socket#listen
Socket.accept_loop Socket#accept_nonblock Socket.tcp Socket.tcp_without_fast_fallback Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo.connect Addrinfo.connect_internal Socket.new Socket#cennect 3VCZ͓ͬͯ͠Ζ͍ ͷίʔϧελοΫ $࣮ $࣮ $࣮ $࣮ $࣮ $࣮ ͷίʔϧελοΫ -
ͦΕΒ3VCZͷίʔυͷதͰ 4PDLFUΦϒδΣΫτͷϝιουݺͼग़͠ͱͯ͠දݱ͞ΕΔ 3VCZ͓ͬͯ͠Ζ͍ Socket.tcp Socket.tcp_without_fast_fallback Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo.connect Addrinfo.connect_internal Socket.new
Socket#cennect ͷίʔϧελοΫ $࣮ $࣮ Socket.tcp_server_loop Socket.tcp_server_sockets Addrinfo.foreach Addrinfo.getaddrinfo Addrinfo#listen Socket.new Socket#bind Socket#listen Socket.accept_loop Socket#accept_nonblock $࣮ $࣮ $࣮ $࣮ ͷίʔϧελοΫ -
͍͜͠ͱͯ͢3VCZࣗͷதʹӅ͞Ε͍ͯΔ Θͨͨͪ͠ιέοτΛ ;ͭ͏ͷ3VCZΦϒδΣΫτͱͯ͠ѻ͏͜ͱ͕Ͱ͖Δ 3VCZ͓ͬͯ͠Ζ͍ Socket.new socket Socket#connect connect Socket#bind bind
Socket#listen listen Socket#accept_nonblock accept ɾ ɾ ɾ ɾ ɾ ➡︎ ➡︎ ➡︎ ➡︎ ➡︎ γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ γεςϜίʔϧ -
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ ࢀߟਤॻ ɾ83JDIBSE4UFWFOT ࣰాཅҰ ༁ ɹʮ6/*9ωοτϫʔΫϓϩάϥϛϯά7PMୈ൛ ɹωοτϫʔΫ"1*ιέοτͱ95*ʯ ͨͷ͍͠4PDLFUͷ͘͠Έ
Socket Under a Microscope