class Celluloid::IO::TCPSocket
TCPSocket with combined blocking and evented support
Public Class Methods
from_ruby_socket(ruby_socket)
click to toggle source
Convert a Ruby TCPSocket into a Celluloid::IO::TCPSocket DEPRECATED: to be removed in a future release @deprecated Use {Celluloid::IO::TCPSocket#new} instead.
# File lib/celluloid/io/tcp_socket.rb, line 28 def self.from_ruby_socket(ruby_socket) new(ruby_socket) end
new(*args)
click to toggle source
@overload initialize(remote_host, remote_port = nil, local_host = nil, local_port = nil)
Opens a TCP connection to remote_host on remote_port. If local_host and local_port are specified, then those parameters are used on the local end to establish the connection. @param remote_host [String, Resolv::IPv4, Resolv::IPv6] @param remote_port [Numeric] @param local_host [String] @param local_port [Numeric]
@overload initialize(socket)
Wraps an already existing tcp socket. @param socket [::TCPSocket]
Calls superclass method
Celluloid::IO::Stream.new
# File lib/celluloid/io/tcp_socket.rb, line 45 def initialize(*args) if args.first.kind_of? ::BasicSocket # socket socket = args.first fail ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1 fail ArgumentError, "wrong kind of socket (#{socket.class} for TCPSocket)" unless socket.kind_of? ::TCPSocket super(socket) else super(create_socket(*args)) end end
open(*args) { |sock| ... }
click to toggle source
Open a TCP socket, yielding it to the given block and closing it automatically when done (if a block is given)
# File lib/celluloid/io/tcp_socket.rb, line 14 def self.open(*args, &_block) sock = new(*args) return sock unless block_given? begin yield(sock) ensure sock.close end end
Public Instance Methods
addr()
click to toggle source
@return [Resolv::IPv4, Resolv::IPv6]
# File lib/celluloid/io/tcp_socket.rb, line 71 def addr socket = to_io ra = socket.remote_address if ra.ipv4? return Resolv::IPv4.create(ra.ip_address) elsif ra.ipv6? return Resolv::IPv6.create(ra.ip_address) else raise ArgumentError, "not an ip socket: #{socket.inspect}" end end
recv(maxlen, flags = nil)
click to toggle source
Receives a message
# File lib/celluloid/io/tcp_socket.rb, line 58 def recv(maxlen, flags = nil) fail NotImplementedError, "flags not supported" if flags && !flags.zero? readpartial(maxlen) end
send(msg, flags, dest_sockaddr = nil)
click to toggle source
Send a message
# File lib/celluloid/io/tcp_socket.rb, line 64 def send(msg, flags, dest_sockaddr = nil) fail NotImplementedError, "dest_sockaddr not supported" if dest_sockaddr fail NotImplementedError, "flags not supported" unless flags.zero? write(msg) end
Private Instance Methods
create_socket(remote_host, remote_port = nil, local_host = nil, local_port = nil)
click to toggle source
# File lib/celluloid/io/tcp_socket.rb, line 84 def create_socket(remote_host, remote_port = nil, local_host = nil, local_port = nil) # Is it an IPv4 address? begin addr = Resolv::IPv4.create(remote_host) rescue ArgumentError end # Guess it's not IPv4! Is it IPv6? unless addr begin addr = Resolv::IPv6.create(remote_host) rescue ArgumentError end end # Guess it's not an IP address, so let's try DNS unless addr addrs = Array(DNSResolver.new.resolve(remote_host)) fail Resolv::ResolvError, "DNS result has no information for #{remote_host}" if addrs.empty? # Pseudorandom round-robin DNS support :/ addr = addrs[rand(addrs.size)] end case addr when Resolv::IPv4 family = Socket::AF_INET when Resolv::IPv6 family = Socket::AF_INET6 else fail ArgumentError, "unsupported address class: #{addr.class}" end socket = Socket.new(family, Socket::SOCK_STREAM, 0) socket.bind Addrinfo.tcp(local_host, local_port) if local_host begin socket.connect_nonblock Socket.sockaddr_in(remote_port, addr.to_s) rescue Errno::EINPROGRESS, Errno::EALREADY # JRuby raises EINPROGRESS, MRI raises EALREADY Celluloid::IO.wait_writable(socket) # HAX: for some reason we need to finish_connect ourselves on JRuby # This logic is unnecessary but JRuby still throws Errno::EINPROGRESS # if we retry the non-blocking connect instead of just finishing it retry unless RUBY_PLATFORM == "java" && socket.to_channel.finish_connect rescue Errno::EISCONN # We're now connected! Yay exceptions for flow control # NOTE: This is the approach the Ruby stdlib docs suggest ;_; end return socket end