Edit File by line
/home/barbar84/www/wp-conte.../plugins/sujqvwi/ExeBy/exe_root.../opt/alt/ruby22/lib64/ruby/2.2.0
File: socket.rb
require 'socket.so'
[0] Fix | Delete
[1] Fix | Delete
class Addrinfo
[2] Fix | Delete
# creates an Addrinfo object from the arguments.
[3] Fix | Delete
#
[4] Fix | Delete
# The arguments are interpreted as similar to self.
[5] Fix | Delete
#
[6] Fix | Delete
# Addrinfo.tcp("0.0.0.0", 4649).family_addrinfo("www.ruby-lang.org", 80)
[7] Fix | Delete
# #=> #<Addrinfo: 221.186.184.68:80 TCP (www.ruby-lang.org:80)>
[8] Fix | Delete
#
[9] Fix | Delete
# Addrinfo.unix("/tmp/sock").family_addrinfo("/tmp/sock2")
[10] Fix | Delete
# #=> #<Addrinfo: /tmp/sock2 SOCK_STREAM>
[11] Fix | Delete
#
[12] Fix | Delete
def family_addrinfo(*args)
[13] Fix | Delete
if args.empty?
[14] Fix | Delete
raise ArgumentError, "no address specified"
[15] Fix | Delete
elsif Addrinfo === args.first
[16] Fix | Delete
raise ArgumentError, "too many arguments" if args.length != 1
[17] Fix | Delete
addrinfo = args.first
[18] Fix | Delete
if (self.pfamily != addrinfo.pfamily) ||
[19] Fix | Delete
(self.socktype != addrinfo.socktype)
[20] Fix | Delete
raise ArgumentError, "Addrinfo type mismatch"
[21] Fix | Delete
end
[22] Fix | Delete
addrinfo
[23] Fix | Delete
elsif self.ip?
[24] Fix | Delete
raise ArgumentError, "IP address needs host and port but #{args.length} arguments given" if args.length != 2
[25] Fix | Delete
host, port = args
[26] Fix | Delete
Addrinfo.getaddrinfo(host, port, self.pfamily, self.socktype, self.protocol)[0]
[27] Fix | Delete
elsif self.unix?
[28] Fix | Delete
raise ArgumentError, "UNIX socket needs single path argument but #{args.length} arguments given" if args.length != 1
[29] Fix | Delete
path, = args
[30] Fix | Delete
Addrinfo.unix(path)
[31] Fix | Delete
else
[32] Fix | Delete
raise ArgumentError, "unexpected family"
[33] Fix | Delete
end
[34] Fix | Delete
end
[35] Fix | Delete
[36] Fix | Delete
# creates a new Socket connected to the address of +local_addrinfo+.
[37] Fix | Delete
#
[38] Fix | Delete
# If _local_addrinfo_ is nil, the address of the socket is not bound.
[39] Fix | Delete
#
[40] Fix | Delete
# The _timeout_ specify the seconds for timeout.
[41] Fix | Delete
# Errno::ETIMEDOUT is raised when timeout occur.
[42] Fix | Delete
#
[43] Fix | Delete
# If a block is given the created socket is yielded for each address.
[44] Fix | Delete
#
[45] Fix | Delete
def connect_internal(local_addrinfo, timeout=nil) # :yields: socket
[46] Fix | Delete
sock = Socket.new(self.pfamily, self.socktype, self.protocol)
[47] Fix | Delete
begin
[48] Fix | Delete
sock.ipv6only! if self.ipv6?
[49] Fix | Delete
sock.bind local_addrinfo if local_addrinfo
[50] Fix | Delete
if timeout
[51] Fix | Delete
begin
[52] Fix | Delete
sock.connect_nonblock(self)
[53] Fix | Delete
rescue IO::WaitWritable
[54] Fix | Delete
if !IO.select(nil, [sock], nil, timeout)
[55] Fix | Delete
raise Errno::ETIMEDOUT, 'user specified timeout'
[56] Fix | Delete
end
[57] Fix | Delete
begin
[58] Fix | Delete
sock.connect_nonblock(self) # check connection failure
[59] Fix | Delete
rescue Errno::EISCONN
[60] Fix | Delete
end
[61] Fix | Delete
end
[62] Fix | Delete
else
[63] Fix | Delete
sock.connect(self)
[64] Fix | Delete
end
[65] Fix | Delete
rescue Exception
[66] Fix | Delete
sock.close
[67] Fix | Delete
raise
[68] Fix | Delete
end
[69] Fix | Delete
if block_given?
[70] Fix | Delete
begin
[71] Fix | Delete
yield sock
[72] Fix | Delete
ensure
[73] Fix | Delete
sock.close if !sock.closed?
[74] Fix | Delete
end
[75] Fix | Delete
else
[76] Fix | Delete
sock
[77] Fix | Delete
end
[78] Fix | Delete
end
[79] Fix | Delete
private :connect_internal
[80] Fix | Delete
[81] Fix | Delete
# :call-seq:
[82] Fix | Delete
# addrinfo.connect_from([local_addr_args], [opts]) {|socket| ... }
[83] Fix | Delete
# addrinfo.connect_from([local_addr_args], [opts])
[84] Fix | Delete
#
[85] Fix | Delete
# creates a socket connected to the address of self.
[86] Fix | Delete
#
[87] Fix | Delete
# If one or more arguments given as _local_addr_args_,
[88] Fix | Delete
# it is used as the local address of the socket.
[89] Fix | Delete
# _local_addr_args_ is given for family_addrinfo to obtain actual address.
[90] Fix | Delete
#
[91] Fix | Delete
# If _local_addr_args_ is not given, the local address of the socket is not bound.
[92] Fix | Delete
#
[93] Fix | Delete
# The optional last argument _opts_ is options represented by a hash.
[94] Fix | Delete
# _opts_ may have following options:
[95] Fix | Delete
#
[96] Fix | Delete
# [:timeout] specify the timeout in seconds.
[97] Fix | Delete
#
[98] Fix | Delete
# If a block is given, it is called with the socket and the value of the block is returned.
[99] Fix | Delete
# The socket is returned otherwise.
[100] Fix | Delete
#
[101] Fix | Delete
# Addrinfo.tcp("www.ruby-lang.org", 80).connect_from("0.0.0.0", 4649) {|s|
[102] Fix | Delete
# s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
[103] Fix | Delete
# puts s.read
[104] Fix | Delete
# }
[105] Fix | Delete
#
[106] Fix | Delete
# # Addrinfo object can be taken for the argument.
[107] Fix | Delete
# Addrinfo.tcp("www.ruby-lang.org", 80).connect_from(Addrinfo.tcp("0.0.0.0", 4649)) {|s|
[108] Fix | Delete
# s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
[109] Fix | Delete
# puts s.read
[110] Fix | Delete
# }
[111] Fix | Delete
#
[112] Fix | Delete
def connect_from(*args, &block)
[113] Fix | Delete
opts = Hash === args.last ? args.pop : {}
[114] Fix | Delete
local_addr_args = args
[115] Fix | Delete
connect_internal(family_addrinfo(*local_addr_args), opts[:timeout], &block)
[116] Fix | Delete
end
[117] Fix | Delete
[118] Fix | Delete
# :call-seq:
[119] Fix | Delete
# addrinfo.connect([opts]) {|socket| ... }
[120] Fix | Delete
# addrinfo.connect([opts])
[121] Fix | Delete
#
[122] Fix | Delete
# creates a socket connected to the address of self.
[123] Fix | Delete
#
[124] Fix | Delete
# The optional argument _opts_ is options represented by a hash.
[125] Fix | Delete
# _opts_ may have following options:
[126] Fix | Delete
#
[127] Fix | Delete
# [:timeout] specify the timeout in seconds.
[128] Fix | Delete
#
[129] Fix | Delete
# If a block is given, it is called with the socket and the value of the block is returned.
[130] Fix | Delete
# The socket is returned otherwise.
[131] Fix | Delete
#
[132] Fix | Delete
# Addrinfo.tcp("www.ruby-lang.org", 80).connect {|s|
[133] Fix | Delete
# s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
[134] Fix | Delete
# puts s.read
[135] Fix | Delete
# }
[136] Fix | Delete
#
[137] Fix | Delete
def connect(opts={}, &block)
[138] Fix | Delete
connect_internal(nil, opts[:timeout], &block)
[139] Fix | Delete
end
[140] Fix | Delete
[141] Fix | Delete
# :call-seq:
[142] Fix | Delete
# addrinfo.connect_to([remote_addr_args], [opts]) {|socket| ... }
[143] Fix | Delete
# addrinfo.connect_to([remote_addr_args], [opts])
[144] Fix | Delete
#
[145] Fix | Delete
# creates a socket connected to _remote_addr_args_ and bound to self.
[146] Fix | Delete
#
[147] Fix | Delete
# The optional last argument _opts_ is options represented by a hash.
[148] Fix | Delete
# _opts_ may have following options:
[149] Fix | Delete
#
[150] Fix | Delete
# [:timeout] specify the timeout in seconds.
[151] Fix | Delete
#
[152] Fix | Delete
# If a block is given, it is called with the socket and the value of the block is returned.
[153] Fix | Delete
# The socket is returned otherwise.
[154] Fix | Delete
#
[155] Fix | Delete
# Addrinfo.tcp("0.0.0.0", 4649).connect_to("www.ruby-lang.org", 80) {|s|
[156] Fix | Delete
# s.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
[157] Fix | Delete
# puts s.read
[158] Fix | Delete
# }
[159] Fix | Delete
#
[160] Fix | Delete
def connect_to(*args, &block)
[161] Fix | Delete
opts = Hash === args.last ? args.pop : {}
[162] Fix | Delete
remote_addr_args = args
[163] Fix | Delete
remote_addrinfo = family_addrinfo(*remote_addr_args)
[164] Fix | Delete
remote_addrinfo.send(:connect_internal, self, opts[:timeout], &block)
[165] Fix | Delete
end
[166] Fix | Delete
[167] Fix | Delete
# creates a socket bound to self.
[168] Fix | Delete
#
[169] Fix | Delete
# If a block is given, it is called with the socket and the value of the block is returned.
[170] Fix | Delete
# The socket is returned otherwise.
[171] Fix | Delete
#
[172] Fix | Delete
# Addrinfo.udp("0.0.0.0", 9981).bind {|s|
[173] Fix | Delete
# s.local_address.connect {|s| s.send "hello", 0 }
[174] Fix | Delete
# p s.recv(10) #=> "hello"
[175] Fix | Delete
# }
[176] Fix | Delete
#
[177] Fix | Delete
def bind
[178] Fix | Delete
sock = Socket.new(self.pfamily, self.socktype, self.protocol)
[179] Fix | Delete
begin
[180] Fix | Delete
sock.ipv6only! if self.ipv6?
[181] Fix | Delete
sock.setsockopt(:SOCKET, :REUSEADDR, 1)
[182] Fix | Delete
sock.bind(self)
[183] Fix | Delete
rescue Exception
[184] Fix | Delete
sock.close
[185] Fix | Delete
raise
[186] Fix | Delete
end
[187] Fix | Delete
if block_given?
[188] Fix | Delete
begin
[189] Fix | Delete
yield sock
[190] Fix | Delete
ensure
[191] Fix | Delete
sock.close if !sock.closed?
[192] Fix | Delete
end
[193] Fix | Delete
else
[194] Fix | Delete
sock
[195] Fix | Delete
end
[196] Fix | Delete
end
[197] Fix | Delete
[198] Fix | Delete
# creates a listening socket bound to self.
[199] Fix | Delete
def listen(backlog=Socket::SOMAXCONN)
[200] Fix | Delete
sock = Socket.new(self.pfamily, self.socktype, self.protocol)
[201] Fix | Delete
begin
[202] Fix | Delete
sock.ipv6only! if self.ipv6?
[203] Fix | Delete
sock.setsockopt(:SOCKET, :REUSEADDR, 1)
[204] Fix | Delete
sock.bind(self)
[205] Fix | Delete
sock.listen(backlog)
[206] Fix | Delete
rescue Exception
[207] Fix | Delete
sock.close
[208] Fix | Delete
raise
[209] Fix | Delete
end
[210] Fix | Delete
if block_given?
[211] Fix | Delete
begin
[212] Fix | Delete
yield sock
[213] Fix | Delete
ensure
[214] Fix | Delete
sock.close if !sock.closed?
[215] Fix | Delete
end
[216] Fix | Delete
else
[217] Fix | Delete
sock
[218] Fix | Delete
end
[219] Fix | Delete
end
[220] Fix | Delete
[221] Fix | Delete
# iterates over the list of Addrinfo objects obtained by Addrinfo.getaddrinfo.
[222] Fix | Delete
#
[223] Fix | Delete
# Addrinfo.foreach(nil, 80) {|x| p x }
[224] Fix | Delete
# #=> #<Addrinfo: 127.0.0.1:80 TCP (:80)>
[225] Fix | Delete
# # #<Addrinfo: 127.0.0.1:80 UDP (:80)>
[226] Fix | Delete
# # #<Addrinfo: [::1]:80 TCP (:80)>
[227] Fix | Delete
# # #<Addrinfo: [::1]:80 UDP (:80)>
[228] Fix | Delete
#
[229] Fix | Delete
def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, &block)
[230] Fix | Delete
Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags).each(&block)
[231] Fix | Delete
end
[232] Fix | Delete
end
[233] Fix | Delete
[234] Fix | Delete
class BasicSocket < IO
[235] Fix | Delete
# Returns an address of the socket suitable for connect in the local machine.
[236] Fix | Delete
#
[237] Fix | Delete
# This method returns _self_.local_address, except following condition.
[238] Fix | Delete
#
[239] Fix | Delete
# - IPv4 unspecified address (0.0.0.0) is replaced by IPv4 loopback address (127.0.0.1).
[240] Fix | Delete
# - IPv6 unspecified address (::) is replaced by IPv6 loopback address (::1).
[241] Fix | Delete
#
[242] Fix | Delete
# If the local address is not suitable for connect, SocketError is raised.
[243] Fix | Delete
# IPv4 and IPv6 address which port is 0 is not suitable for connect.
[244] Fix | Delete
# Unix domain socket which has no path is not suitable for connect.
[245] Fix | Delete
#
[246] Fix | Delete
# Addrinfo.tcp("0.0.0.0", 0).listen {|serv|
[247] Fix | Delete
# p serv.connect_address #=> #<Addrinfo: 127.0.0.1:53660 TCP>
[248] Fix | Delete
# serv.connect_address.connect {|c|
[249] Fix | Delete
# s, _ = serv.accept
[250] Fix | Delete
# p [c, s] #=> [#<Socket:fd 4>, #<Socket:fd 6>]
[251] Fix | Delete
# }
[252] Fix | Delete
# }
[253] Fix | Delete
#
[254] Fix | Delete
def connect_address
[255] Fix | Delete
addr = local_address
[256] Fix | Delete
afamily = addr.afamily
[257] Fix | Delete
if afamily == Socket::AF_INET
[258] Fix | Delete
raise SocketError, "unbound IPv4 socket" if addr.ip_port == 0
[259] Fix | Delete
if addr.ip_address == "0.0.0.0"
[260] Fix | Delete
addr = Addrinfo.new(["AF_INET", addr.ip_port, nil, "127.0.0.1"], addr.pfamily, addr.socktype, addr.protocol)
[261] Fix | Delete
end
[262] Fix | Delete
elsif defined?(Socket::AF_INET6) && afamily == Socket::AF_INET6
[263] Fix | Delete
raise SocketError, "unbound IPv6 socket" if addr.ip_port == 0
[264] Fix | Delete
if addr.ip_address == "::"
[265] Fix | Delete
addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
[266] Fix | Delete
elsif addr.ip_address == "0.0.0.0" # MacOS X 10.4 returns "a.b.c.d" for IPv4-mapped IPv6 address.
[267] Fix | Delete
addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
[268] Fix | Delete
elsif addr.ip_address == "::ffff:0.0.0.0" # MacOS X 10.6 returns "::ffff:a.b.c.d" for IPv4-mapped IPv6 address.
[269] Fix | Delete
addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
[270] Fix | Delete
end
[271] Fix | Delete
elsif defined?(Socket::AF_UNIX) && afamily == Socket::AF_UNIX
[272] Fix | Delete
raise SocketError, "unbound Unix socket" if addr.unix_path == ""
[273] Fix | Delete
end
[274] Fix | Delete
addr
[275] Fix | Delete
end
[276] Fix | Delete
end
[277] Fix | Delete
[278] Fix | Delete
class Socket < BasicSocket
[279] Fix | Delete
# enable the socket option IPV6_V6ONLY if IPV6_V6ONLY is available.
[280] Fix | Delete
def ipv6only!
[281] Fix | Delete
if defined? Socket::IPV6_V6ONLY
[282] Fix | Delete
self.setsockopt(:IPV6, :V6ONLY, 1)
[283] Fix | Delete
end
[284] Fix | Delete
end
[285] Fix | Delete
[286] Fix | Delete
# :call-seq:
[287] Fix | Delete
# Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... }
[288] Fix | Delete
# Socket.tcp(host, port, local_host=nil, local_port=nil, [opts])
[289] Fix | Delete
#
[290] Fix | Delete
# creates a new socket object connected to host:port using TCP/IP.
[291] Fix | Delete
#
[292] Fix | Delete
# If local_host:local_port is given,
[293] Fix | Delete
# the socket is bound to it.
[294] Fix | Delete
#
[295] Fix | Delete
# The optional last argument _opts_ is options represented by a hash.
[296] Fix | Delete
# _opts_ may have following options:
[297] Fix | Delete
#
[298] Fix | Delete
# [:connect_timeout] specify the timeout in seconds.
[299] Fix | Delete
#
[300] Fix | Delete
# If a block is given, the block is called with the socket.
[301] Fix | Delete
# The value of the block is returned.
[302] Fix | Delete
# The socket is closed when this method returns.
[303] Fix | Delete
#
[304] Fix | Delete
# If no block is given, the socket is returned.
[305] Fix | Delete
#
[306] Fix | Delete
# Socket.tcp("www.ruby-lang.org", 80) {|sock|
[307] Fix | Delete
# sock.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
[308] Fix | Delete
# sock.close_write
[309] Fix | Delete
# puts sock.read
[310] Fix | Delete
# }
[311] Fix | Delete
#
[312] Fix | Delete
def self.tcp(host, port, *rest) # :yield: socket
[313] Fix | Delete
opts = Hash === rest.last ? rest.pop : {}
[314] Fix | Delete
raise ArgumentError, "wrong number of arguments (#{rest.length} for 2)" if 2 < rest.length
[315] Fix | Delete
local_host, local_port = rest
[316] Fix | Delete
last_error = nil
[317] Fix | Delete
ret = nil
[318] Fix | Delete
[319] Fix | Delete
connect_timeout = opts[:connect_timeout]
[320] Fix | Delete
[321] Fix | Delete
local_addr_list = nil
[322] Fix | Delete
if local_host != nil || local_port != nil
[323] Fix | Delete
local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil)
[324] Fix | Delete
end
[325] Fix | Delete
[326] Fix | Delete
Addrinfo.foreach(host, port, nil, :STREAM) {|ai|
[327] Fix | Delete
if local_addr_list
[328] Fix | Delete
local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily }
[329] Fix | Delete
next if !local_addr
[330] Fix | Delete
else
[331] Fix | Delete
local_addr = nil
[332] Fix | Delete
end
[333] Fix | Delete
begin
[334] Fix | Delete
sock = local_addr ?
[335] Fix | Delete
ai.connect_from(local_addr, :timeout => connect_timeout) :
[336] Fix | Delete
ai.connect(:timeout => connect_timeout)
[337] Fix | Delete
rescue SystemCallError
[338] Fix | Delete
last_error = $!
[339] Fix | Delete
next
[340] Fix | Delete
end
[341] Fix | Delete
ret = sock
[342] Fix | Delete
break
[343] Fix | Delete
}
[344] Fix | Delete
if !ret
[345] Fix | Delete
if last_error
[346] Fix | Delete
raise last_error
[347] Fix | Delete
else
[348] Fix | Delete
raise SocketError, "no appropriate local address"
[349] Fix | Delete
end
[350] Fix | Delete
end
[351] Fix | Delete
if block_given?
[352] Fix | Delete
begin
[353] Fix | Delete
yield ret
[354] Fix | Delete
ensure
[355] Fix | Delete
ret.close if !ret.closed?
[356] Fix | Delete
end
[357] Fix | Delete
else
[358] Fix | Delete
ret
[359] Fix | Delete
end
[360] Fix | Delete
end
[361] Fix | Delete
[362] Fix | Delete
# :stopdoc:
[363] Fix | Delete
def self.ip_sockets_port0(ai_list, reuseaddr)
[364] Fix | Delete
sockets = []
[365] Fix | Delete
begin
[366] Fix | Delete
sockets.clear
[367] Fix | Delete
port = nil
[368] Fix | Delete
ai_list.each {|ai|
[369] Fix | Delete
begin
[370] Fix | Delete
s = Socket.new(ai.pfamily, ai.socktype, ai.protocol)
[371] Fix | Delete
rescue SystemCallError
[372] Fix | Delete
next
[373] Fix | Delete
end
[374] Fix | Delete
sockets << s
[375] Fix | Delete
s.ipv6only! if ai.ipv6?
[376] Fix | Delete
if reuseaddr
[377] Fix | Delete
s.setsockopt(:SOCKET, :REUSEADDR, 1)
[378] Fix | Delete
end
[379] Fix | Delete
if !port
[380] Fix | Delete
s.bind(ai)
[381] Fix | Delete
port = s.local_address.ip_port
[382] Fix | Delete
else
[383] Fix | Delete
s.bind(ai.family_addrinfo(ai.ip_address, port))
[384] Fix | Delete
end
[385] Fix | Delete
}
[386] Fix | Delete
rescue Errno::EADDRINUSE
[387] Fix | Delete
sockets.each {|s| s.close }
[388] Fix | Delete
retry
[389] Fix | Delete
rescue Exception
[390] Fix | Delete
sockets.each {|s| s.close }
[391] Fix | Delete
raise
[392] Fix | Delete
end
[393] Fix | Delete
sockets
[394] Fix | Delete
end
[395] Fix | Delete
class << self
[396] Fix | Delete
private :ip_sockets_port0
[397] Fix | Delete
end
[398] Fix | Delete
[399] Fix | Delete
def self.tcp_server_sockets_port0(host)
[400] Fix | Delete
ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE)
[401] Fix | Delete
sockets = ip_sockets_port0(ai_list, true)
[402] Fix | Delete
begin
[403] Fix | Delete
sockets.each {|s|
[404] Fix | Delete
s.listen(Socket::SOMAXCONN)
[405] Fix | Delete
}
[406] Fix | Delete
rescue Exception
[407] Fix | Delete
sockets.each {|s| s.close }
[408] Fix | Delete
raise
[409] Fix | Delete
end
[410] Fix | Delete
sockets
[411] Fix | Delete
end
[412] Fix | Delete
class << self
[413] Fix | Delete
private :tcp_server_sockets_port0
[414] Fix | Delete
end
[415] Fix | Delete
# :startdoc:
[416] Fix | Delete
[417] Fix | Delete
# creates TCP/IP server sockets for _host_ and _port_.
[418] Fix | Delete
# _host_ is optional.
[419] Fix | Delete
#
[420] Fix | Delete
# If no block given,
[421] Fix | Delete
# it returns an array of listening sockets.
[422] Fix | Delete
#
[423] Fix | Delete
# If a block is given, the block is called with the sockets.
[424] Fix | Delete
# The value of the block is returned.
[425] Fix | Delete
# The socket is closed when this method returns.
[426] Fix | Delete
#
[427] Fix | Delete
# If _port_ is 0, actual port number is chosen dynamically.
[428] Fix | Delete
# However all sockets in the result has same port number.
[429] Fix | Delete
#
[430] Fix | Delete
# # tcp_server_sockets returns two sockets.
[431] Fix | Delete
# sockets = Socket.tcp_server_sockets(1296)
[432] Fix | Delete
# p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>]
[433] Fix | Delete
#
[434] Fix | Delete
# # The sockets contains IPv6 and IPv4 sockets.
[435] Fix | Delete
# sockets.each {|s| p s.local_address }
[436] Fix | Delete
# #=> #<Addrinfo: [::]:1296 TCP>
[437] Fix | Delete
# # #<Addrinfo: 0.0.0.0:1296 TCP>
[438] Fix | Delete
#
[439] Fix | Delete
# # IPv6 and IPv4 socket has same port number, 53114, even if it is chosen dynamically.
[440] Fix | Delete
# sockets = Socket.tcp_server_sockets(0)
[441] Fix | Delete
# sockets.each {|s| p s.local_address }
[442] Fix | Delete
# #=> #<Addrinfo: [::]:53114 TCP>
[443] Fix | Delete
# # #<Addrinfo: 0.0.0.0:53114 TCP>
[444] Fix | Delete
#
[445] Fix | Delete
# # The block is called with the sockets.
[446] Fix | Delete
# Socket.tcp_server_sockets(0) {|sockets|
[447] Fix | Delete
# p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>]
[448] Fix | Delete
# }
[449] Fix | Delete
#
[450] Fix | Delete
def self.tcp_server_sockets(host=nil, port)
[451] Fix | Delete
if port == 0
[452] Fix | Delete
sockets = tcp_server_sockets_port0(host)
[453] Fix | Delete
else
[454] Fix | Delete
last_error = nil
[455] Fix | Delete
sockets = []
[456] Fix | Delete
begin
[457] Fix | Delete
Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai|
[458] Fix | Delete
begin
[459] Fix | Delete
s = ai.listen
[460] Fix | Delete
rescue SystemCallError
[461] Fix | Delete
last_error = $!
[462] Fix | Delete
next
[463] Fix | Delete
end
[464] Fix | Delete
sockets << s
[465] Fix | Delete
}
[466] Fix | Delete
if sockets.empty?
[467] Fix | Delete
raise last_error
[468] Fix | Delete
end
[469] Fix | Delete
rescue Exception
[470] Fix | Delete
sockets.each {|s| s.close }
[471] Fix | Delete
raise
[472] Fix | Delete
end
[473] Fix | Delete
end
[474] Fix | Delete
if block_given?
[475] Fix | Delete
begin
[476] Fix | Delete
yield sockets
[477] Fix | Delete
ensure
[478] Fix | Delete
sockets.each {|s| s.close if !s.closed? }
[479] Fix | Delete
end
[480] Fix | Delete
else
[481] Fix | Delete
sockets
[482] Fix | Delete
end
[483] Fix | Delete
end
[484] Fix | Delete
[485] Fix | Delete
# yield socket and client address for each a connection accepted via given sockets.
[486] Fix | Delete
#
[487] Fix | Delete
# The arguments are a list of sockets.
[488] Fix | Delete
# The individual argument should be a socket or an array of sockets.
[489] Fix | Delete
#
[490] Fix | Delete
# This method yields the block sequentially.
[491] Fix | Delete
# It means that the next connection is not accepted until the block returns.
[492] Fix | Delete
# So concurrent mechanism, thread for example, should be used to service multiple clients at a time.
[493] Fix | Delete
#
[494] Fix | Delete
def self.accept_loop(*sockets) # :yield: socket, client_addrinfo
[495] Fix | Delete
sockets.flatten!(1)
[496] Fix | Delete
if sockets.empty?
[497] Fix | Delete
raise ArgumentError, "no sockets"
[498] Fix | Delete
end
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function