class Socketry::TCP::Server

Transmission Control Protocol servers: Accept connections from the network

Attributes

read_timeout[R]
resolver[R]
socket_class[R]
write_timeout[R]

Public Class Methods

new( hostname_or_port, port = nil, read_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:read], write_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:write], timer: Socketry::Timeout::DEFAULT_TIMER.new, resolver: Socketry::Resolver::DEFAULT_RESOLVER, server_class: ::TCPServer, socket_class: ::TCPSocket ) click to toggle source

Create a new TCP server

@return [Socketry::TCP::Server]

# File lib/socketry/tcp/server.rb, line 24
def initialize(
  hostname_or_port,
  port = nil,
  read_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:read],
  write_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:write],
  timer: Socketry::Timeout::DEFAULT_TIMER.new,
  resolver: Socketry::Resolver::DEFAULT_RESOLVER,
  server_class: ::TCPServer,
  socket_class: ::TCPSocket
)
  @read_timeout  = read_timeout
  @write_timeout = write_timeout
  @resolver      = resolver
  @socket_class  = socket_class

  if port
    @server = server_class.new(@resolver.resolve(hostname_or_port).to_s, port)
  else
    @server = server_class.new(hostname_or_port)
  end

  start_timer(timer)
rescue Errno::EADDRINUSE => ex
  raise AddressInUseError, ex.message, ex.backtrace
end
open(hostname_or_port, port = nil, **args) { |server| ... } click to toggle source

Create a new TCP server, yielding the server socket and auto-closing it

# File lib/socketry/tcp/server.rb, line 14
def self.open(hostname_or_port, port = nil, **args)
  server = new(hostname_or_port, port, **args)
  result = yield server
  server.close
  result
end

Public Instance Methods

accept(timeout: nil) click to toggle source

Accept a connection to the server

@param timeout [Numeric, NilClass] seconds to wait before aborting the accept @return [Socketry::TCP::Socket]

# File lib/socketry/tcp/server.rb, line 54
def accept(timeout: nil)
  set_timeout(timeout)

  begin
    # Note: `exception: false` for TCPServer#accept_nonblock is only supported in Ruby 2.3+
    ruby_socket = @server.accept_nonblock
  rescue IO::WaitReadable, Errno::EAGAIN
    # Ruby 2.2 has trouble using io/wait here
    retry if IO.select([@server], nil, nil, time_remaining(timeout))
    raise Socketry::TimeoutError, "no connection received after #{timeout} seconds"
  end

  Socketry::TCP::Socket.new(
    read_timeout:  @read_timeout,
    write_timeout: @write_timeout,
    resolver:      @resolver,
    socket_class:  @socket_class
  ).from_socket(ruby_socket)
ensure
  clear_timeout(timeout)
end
close() click to toggle source

Close the server

# File lib/socketry/tcp/server.rb, line 77
def close
  return false unless @server
  @server.close rescue nil
  @server = nil
  true
end