Class | UNIXServer |
In: |
ext/socket/socket.c
|
Parent: | UNIXSocket |
Class Socket provides access to the underlying operating system socket implementations. It can be used to provide more operating system specific functionality than the protocol-specific socket classes but at the expense of greater complexity. In particular, the class handles addresses using +struct sockaddr+ structures packed into Ruby strings, which can be a joy to manipulate.
Ruby‘s implementation of Socket causes an exception to be raised based on the error generated by the system dependent implementation. This is why the methods are documented in a way that isolate Unix-based system exceptions from Windows based exceptions. If more information on particular exception is needed please refer to the Unix manual pages or the Windows WinSock reference.
Much material in this documentation is taken with permission from Programming Ruby from The Pragmatic Bookshelf.
Accepts an incoming connection using accept(2) after O_NONBLOCK is set for the underlying file descriptor. It returns an accepted UNIXSocket for the incoming connection.
require 'socket' serv = UNIXServer.new("/tmp/sock") begin sock = serv.accept_nonblock rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, 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 UNIXServer#accept_nonblock fails.
UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure, including Errno::EAGAIN.
/* * call-seq: * unixserver.accept_nonblock => unixsocket * * Accepts an incoming connection using accept(2) after * O_NONBLOCK is set for the underlying file descriptor. * It returns an accepted UNIXSocket for the incoming connection. * * === Example * require 'socket' * serv = UNIXServer.new("/tmp/sock") * begin * sock = serv.accept_nonblock * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, 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 UNIXServer#accept_nonblock fails. * * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure, * including Errno::EAGAIN. * * === See * * UNIXServer#accept * * Socket#accept */ static VALUE unix_accept_nonblock(sock) VALUE sock; { rb_io_t *fptr; struct sockaddr_un from; socklen_t fromlen; GetOpenFile(sock, fptr); fromlen = sizeof(from); return s_accept_nonblock(rb_cUNIXSocket, fptr, (struct sockaddr *)&from, &fromlen); }
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.
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 )
require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) socket.listen( 1 )
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:
On Windows systems the following system exceptions may be raised if the call to listen fails:
/* * call-seq: * socket.listen( int ) => 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 arbitary 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 approriate 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 commmitted 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 connected * * Errno::EMFILE - no more socket descriptors are available * * Errno::ENOBUFS - no buffer space is available * * Errno::ENOTSOC - +socket+ is not a socket * * Errno::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 sock_listen(sock, log) VALUE sock, log; { rb_io_t *fptr; int backlog; rb_secure(4); backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fileno(fptr->f), backlog) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); }