Class: Socketry::TCP::Server

Inherits:
Object
  • Object
show all
Includes:
Socketry::Timeout
Defined in:
lib/socketry/tcp/server.rb

Overview

Transmission Control Protocol servers: Accept connections from the network

Direct Known Subclasses

SSL::Server

Constant Summary

Constants included from Socketry::Timeout

Socketry::Timeout::DEFAULT_TIMEOUTS, Socketry::Timeout::DEFAULT_TIMER

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Socketry::Timeout

#clear_timeout, #lifetime, #set_timeout, #start_timer, #time_remaining

Constructor Details

#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) ⇒ Socketry::TCP::Server

Create a new TCP server



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 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

Instance Attribute Details

#read_timeoutObject (readonly)

Returns the value of attribute read_timeout.



11
12
13
# File 'lib/socketry/tcp/server.rb', line 11

def read_timeout
  @read_timeout
end

#resolverObject (readonly)

Returns the value of attribute resolver.



11
12
13
# File 'lib/socketry/tcp/server.rb', line 11

def resolver
  @resolver
end

#socket_classObject (readonly)

Returns the value of attribute socket_class.



11
12
13
# File 'lib/socketry/tcp/server.rb', line 11

def socket_class
  @socket_class
end

#write_timeoutObject (readonly)

Returns the value of attribute write_timeout.



11
12
13
# File 'lib/socketry/tcp/server.rb', line 11

def write_timeout
  @write_timeout
end

Class Method Details

.open(hostname_or_port, port = nil, **args) ⇒ Object

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



14
15
16
17
18
19
# 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

Instance Method Details

#accept(timeout: nil) ⇒ Socketry::TCP::Socket

Accept a connection to the server

Parameters:

  • timeout (Numeric, NilClass) (defaults to: nil)

    seconds to wait before aborting the accept

Returns:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 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

#closeObject

Close the server



77
78
79
80
81
82
# File 'lib/socketry/tcp/server.rb', line 77

def close
  return false unless @server
  @server.close rescue nil
  @server = nil
  true
end