On this page
class TCPServer
TCPServer represents a TCP/IP server socket.
A simple TCP server may look like:
require 'socket'
server = TCPServer.new 2000 # Server bind to port 2000
loop do
client = server.accept # Wait for a client to connect
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
A more usable server (serving multiple clients):
require 'socket'
server = TCPServer.new 2000
loop do
Thread.start(server.accept) do |client|
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
end
Public Class Methods
static VALUE
tcp_svr_init(int argc, VALUE *argv, VALUE sock)
{
VALUE hostname, port;
rb_scan_args(argc, argv, "011", &hostname, &port);
return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER);
}
Creates a new server socket bound to port.
If hostname is given, the socket is bound to it.
serv = TCPServer.new("127.0.0.1", 28561)
s = serv.accept
s.puts Time.now
s.close
Internally, ::new calls getaddrinfo() function to obtain addresses. If getaddrinfo() returns multiple addresses, ::new tries to create a server socket for each address and returns first one that is successful.
Public Instance Methods
static VALUE
tcp_accept(VALUE sock)
{
rb_io_t *fptr;
union_sockaddr from;
socklen_t fromlen;
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(from);
return rsock_s_accept(rb_cTCPSocket, fptr->fd, &from.addr, &fromlen);
}
Accepts an incoming connection. It returns a new TCPSocket object.
TCPServer.open("127.0.0.1", 14641) {|serv|
s = serv.accept
s.puts Time.now
s.close
}
# File ext/socket/lib/socket.rb, line 1296
def accept_nonblock(exception: true)
__accept_nonblock(exception)
end
Accepts an incoming connection using accept(2) after O_NONBLOCK is set for the underlying file descriptor. It returns an accepted TCPSocket for the incoming connection.
Example
require 'socket'
serv = TCPServer.new(2202)
begin # emulate blocking accept
sock = serv.accept_nonblock
rescue IO::WaitReadable, Errno::EINTR
IO.select([serv])
retry
end
# sock is an accepted socket.
Refer to Socket#accept for the exceptions that may be thrown if the call to #accept_nonblock fails.
#accept_nonblock may raise any error corresponding to accept(2) failure, including Errno::EWOULDBLOCK.
If the exception is Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, it is extended by IO::WaitReadable. So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
By specifying a keyword argument exception to false
, you can indicate that #accept_nonblock should not raise an IO::WaitReadable exception, but return the symbol :wait_readable
instead.
See
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);
}
Listens for connections, using the specified int
as the backlog. A call to listen only applies if the socket
is of type SOCK_STREAM or SOCK_SEQPACKET.
Parameter
backlog
- the maximum length of the queue for pending connections.
Example 1
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
socket.bind( sockaddr )
socket.listen( 5 )
Example 2 (listening on an arbitrary port, unix-based systems only):
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
socket.listen( 1 )
Unix-based Exceptions
On unix based systems the above will work because a new sockaddr
struct is created on the address ADDR_ANY, for an arbitrary port number as handed off by the kernel. It will not work on Windows, because Windows requires that the socket
is bound by calling bind before it can listen.
If the backlog amount exceeds the implementation-dependent maximum queue length, the implementation's maximum queue length will be used.
On unix-based based systems the following system exceptions may be raised if the call to listen fails:
Errno::EBADF - the socket argument is not a valid file descriptor
Errno::EDESTADDRREQ - the socket is not bound to a local address, and the protocol does not support listening on an unbound socket
Errno::EINVAL - the socket is already connected
Errno::ENOTSOCK - the socket argument does not refer to a socket
Errno::EOPNOTSUPP - the socket protocol does not support listen
Errno::EACCES - the calling process does not have appropriate privileges
Errno::EINVAL - the socket has been shut down
Errno::ENOBUFS - insufficient resources are available in the system to complete the call
Windows Exceptions
On Windows systems the following system exceptions may be raised if the call to listen fails:
Errno::ENETDOWN - the network is down
Errno::EADDRINUSE - the socket's local address is already in use. This usually occurs during the execution of bind but could be delayed if the call to bind was to a partially wildcard address (involving ADDR_ANY) and if a specific address needs to be committed at the time of the call to listen
Errno::EINPROGRESS - a Windows Sockets 1.1 call is in progress or the service provider is still processing a callback function
Errno::EINVAL - the
socket
has not been bound with a call to bind.Errno::EISCONN - the
socket
is already connectedErrno::EMFILE - no more socket descriptors are available
Errno::ENOBUFS - no buffer space is available
Errno::ENOTSOC -
socket
is not a socketErrno::EOPNOTSUPP - the referenced
socket
is not a type that supports the listen method
See
listen manual pages on unix-based systems
listen function in Microsoft's Winsock functions reference
static VALUE
tcp_sysaccept(VALUE sock)
{
rb_io_t *fptr;
union_sockaddr from;
socklen_t fromlen;
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(from);
return rsock_s_accept(0, fptr->fd, &from.addr, &fromlen);
}
Returns a file descriptor of a accepted connection.
TCPServer.open("127.0.0.1", 28561) {|serv|
fd = serv.sysaccept
s = IO.for_fd(fd)
s.puts Time.now
s.close
}
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.