Class: Socket

Inherits:
BasicSocket show all
Defined in:
socket.c

Overview

Socket contains a number of generally useful singleton methods and constants, as well as offering low-level interfaces that can be used to develop socket applications using protocols other than TCP, UDP, and UNIX domain sockets.

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BasicSocket

#close_read, #close_write, do_not_reverse_lookup, do_not_reverse_lookup=, for_fd, #getpeername, #getsockname, #getsockopt, #recv, #recv_nonblock, #send, #setsockopt, #shutdown

Constructor Details

#initializeObject

Class Method Details

.getaddrinfo(host, service, family = nil, socktype = nil, protocol = nil, flags = nil) ⇒ Object

Return address information for host and port. The remaining arguments are hints that limit the address information returned.

This method corresponds closely to the POSIX.1g getaddrinfo() definition.

Parameters

  • host is a host name or an address string (dotted decimal for IPv4, or a hex string for IPv6) for which to return information. A nil is also allowed, its meaning depends on flags, see below.

  • service is a service name (???http???, ???ssh???, ???), or a port number (80, 22, ???), see Socket.getservbyname for more information. A nil is also allowed, meaning zero.

  • family limits the output to a specific address family, one of the Socket::AF_* constants. Socket::AF_INET (IPv4) and Socket::AF_INET6 (IPv6) are the most commonly used families. You will usually pass either nil or Socket::AF_UNSPEC, allowing the IPv6 information to be returned first if host is reachable via IPv6, and IPv4 information otherwise. The two strings ???AF_INET??? or ???AF_INET6??? are also allowed, they are converted to their respective Socket::AF_* constants.

  • socktype limits the output to a specific type of socket, one of the Socket::SOCK_* constants. Socket::SOCK_STREAM (for TCP) and Socket::SOCK_DGRAM (for UDP) are the most commonly used socket types. If nil, then information for all types of sockets supported by service will be returned. You will usually know what type of socket you intend to create, and should pass that socket type in.

  • protocol limits the output to a specific protocol numpber, one of the Socket::IPPROTO_* constants. It is usually implied by the socket type (Socket::SOCK_STREAM => Socket::IPPROTO_TCP, ???), if you pass other than nil you already know what this is for.

  • flags is one of the Socket::AI_* constants. They mean:

    • Socket::AI_PASSIVE: when set, if host is nil the 'any' address will be returned, Socket::INADDR_ANY or 0 for IPv4, "0::0" or "::" for IPv6. This address is suitable for use by servers that will bind their socket and do a passive listen, thus the name of the flag. Otherwise the local or loopback address will be returned, this is "127.0.0.1" for IPv4 and "::1' for IPv6.

    • ...

Returns

Returns an array of arrays, where each subarray contains:

  • address family, a string like "AF_INET" or "AF_INET6"

  • port number, the port number for service

  • host name, either a canonical name for host, or it's address in presentation format if the address could not be looked up.

  • host IP, the address of host in presentation format

  • address family, as a numeric value (one of the Socket::AF_* constants).

  • socket type, as a numeric value (one of the Socket::SOCK_* constants).

  • protocol number, as a numeric value (one of the Socket::IPPROTO_* constants).

The first four values are identical to what is commonly returned as an address array, see IPSocket for more information.

Examples

Not all input combinations are valid, and while there are many combinations, only a few cases are common.

A typical client will call getaddrinfo with the host and service it wants to connect to. It knows that it will attempt to connect with either TCP or UDP, and specifies socktype accordingly. It loops through all returned addresses, and try to connect to them in turn:

addrinfo = Socket::getaddrinfo('www.example.com', 'www', nil, Socket::SOCK_STREAM)
addrinfo.each do |af, port, name, addr|
  begin
    sock = TCPSocket.new(addr, port)
    # ...
    exit 1
  rescue
  end
end

With UDP you don't know if connect suceeded, but if communication fails, the next address can be tried.

A typical server will call getaddrinfo with a host of nil, the service it listens to, and a flags of Socket::AI_PASSIVE. It will listen for connections on the first returned address:

addrinfo = Socket::getaddrinfo(nil, 'www', nil, Socket::SOCK_STREAM, nil, Socket::AI_PASSIVE)
af, port, name, addr = addrinfo.first
sock = TCPServer(addr, port)
while( client = s.accept )
  # ...
end


# File 'socket.c'

/*
 * Document-method: getaddrinfo
 * call-seq: Socket.getaddrinfo(host, service, family=nil, socktype=nil, protocol=nil, flags=nil) => addrinfo
 *
 * Return address information for +host+ and +port+. The remaining arguments
 * are hints that limit the address information returned.
 *
 * This method corresponds closely to the POSIX.1g getaddrinfo() definition.
 *
 * === Parameters
 * - +host+ is a host name or an address string (dotted decimal for IPv4, or a hex string
 *   for IPv6) for which to return information. A nil is also allowed, its meaning
 *   depends on +flags+, see below.
 * - +service+ is a service name ("http", "ssh", ...), or 
 *   a port number (80, 22, ...), see Socket.getservbyname for more
 *   information. A nil is also allowed, meaning zero.
 * - +family+ limits the output to a specific address family, one of the
 *   Socket::AF_* constants. Socket::AF_INET (IPv4) and Socket::AF_INET6 (IPv6)
 *   are the most commonly used families. You will usually pass either nil or
 *   Socket::AF_UNSPEC, allowing the IPv6 information to be returned first if
 *   +host+ is reachable via IPv6, and IPv4 information otherwise.  The two
 *   strings "AF_INET" or "AF_INET6" are also allowed, they are converted to
 *   their respective Socket::AF_* constants.
 * - +socktype+ limits the output to a specific type of socket, one of the
 *   Socket::SOCK_* constants. Socket::SOCK_STREAM (for TCP) and
 *   Socket::SOCK_DGRAM (for UDP) are the most commonly used socket types. If
 *   nil, then information for all types of sockets supported by +service+ will
 *   be returned. You will usually know what type of socket you intend to
 *   create, and should pass that socket type in.
 * - +protocol+ limits the output to a specific protocol numpber, one of the
 *   Socket::IPPROTO_* constants. It is usually implied by the socket type
 *   (Socket::SOCK_STREAM => Socket::IPPROTO_TCP, ...), if you pass other than
 *   nil you already know what this is for.
 * - +flags+ is one of the Socket::AI_* constants. They mean:
 *   - Socket::AI_PASSIVE: when set, if +host+ is nil the 'any' address will be
 *     returned, Socket::INADDR_ANY or 0 for IPv4, "0::0" or "::" for IPv6.  This
 *     address is suitable for use by servers that will bind their socket and do
 *     a passive listen, thus the name of the flag. Otherwise the local or
 *     loopback address will be returned, this is "127.0.0.1" for IPv4 and "::1'
 *     for IPv6.
 *   - ...
 *
 *
 * === Returns
 *
 * Returns an array of arrays, where each subarray contains:
 * - address family, a string like "AF_INET" or "AF_INET6"
 * - port number, the port number for +service+
 * - host name, either a canonical name for +host+, or it's address in presentation
 *   format if the address could not be looked up.
 * - host IP, the address of +host+ in presentation format
 * - address family, as a numeric value (one of the Socket::AF_* constants).
 * - socket type, as a numeric value (one of the Socket::SOCK_* constants).
 * - protocol number, as a numeric value (one of the Socket::IPPROTO_* constants).
 *
 * The first four values are identical to what is commonly returned as an
 * address array, see IPSocket for more information.
 *
 * === Examples
 *
 * Not all input combinations are valid, and while there are many combinations,
 * only a few cases are common.
 *
 * A typical client will call getaddrinfo with the +host+ and +service+ it
 * wants to connect to. It knows that it will attempt to connect with either
 * TCP or UDP, and specifies +socktype+ accordingly. It loops through all
 * returned addresses, and try to connect to them in turn:
 *
 *   addrinfo = Socket::getaddrinfo('www.example.com', 'www', nil, Socket::SOCK_STREAM)
 *   addrinfo.each do |af, port, name, addr|
 *     begin
 *       sock = TCPSocket.new(addr, port)
 *       # ...
 *       exit 1
 *     rescue
 *     end
 *   end
 *
 * With UDP you don't know if connect suceeded, but if communication fails,
 * the next address can be tried.
 *
 * A typical server will call getaddrinfo with a +host+ of nil, the +service+
 * it listens to, and a +flags+ of Socket::AI_PASSIVE. It will listen for
 * connections on the first returned address:
 *   addrinfo = Socket::getaddrinfo(nil, 'www', nil, Socket::SOCK_STREAM, nil, Socket::AI_PASSIVE)
 *   af, port, name, addr = addrinfo.first
 *   sock = TCPServer(addr, port)
 *   while( client = s.accept )
 *     # ...
 *   end
 */
static VALUE
sock_s_getaddrinfo(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE host, port, family, socktype, protocol, flags, ret;
    char hbuf[1024], pbuf[1024];
    char *hptr, *pptr, *ap;
    struct addrinfo hints, *res;
    int error;

    host = port = family = socktype = protocol = flags = Qnil;
    rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol, &flags);
    if (NIL_P(host)) {
    hptr = NULL;
    }
    else {
    strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
    hbuf[sizeof(hbuf) - 1] = '\0';
    hptr = hbuf;
    }
    if (NIL_P(port)) {
    pptr = NULL;
    }
    else if (FIXNUM_P(port)) {
    snprintf(pbuf, sizeof(pbuf), "%ld", FIX2LONG(port));
    pptr = pbuf;
    }
    else {
    strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
    pbuf[sizeof(pbuf) - 1] = '\0';
    pptr = pbuf;
    }

    MEMZERO(&hints, struct addrinfo, 1);
    if (NIL_P(family)) {
    hints.ai_family = PF_UNSPEC;
    }
    else if (FIXNUM_P(family)) {
    hints.ai_family = FIX2INT(family);
    }
    else if ((ap = StringValuePtr(family)) != 0) {
    if (strcmp(ap, "AF_INET") == 0) {
        hints.ai_family = PF_INET;
    }
#ifdef INET6
    else if (strcmp(ap, "AF_INET6") == 0) {
        hints.ai_family = PF_INET6;
    }
#endif
    }

    if (!NIL_P(socktype)) {
    hints.ai_socktype = NUM2INT(socktype);
    }
    if (!NIL_P(protocol)) {
    hints.ai_protocol = NUM2INT(protocol);
    }
    if (!NIL_P(flags)) {
    hints.ai_flags = NUM2INT(flags);
    }
    error = getaddrinfo(hptr, pptr, &hints, &res);
    if (error) {
    rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
    }

    ret = make_addrinfo(res);
    freeaddrinfo(res);
    return ret;
}

.gethostbyaddrObject

.gethostbyname(host) ⇒ Object

Resolve host and return name and address information for it, similarly to gethostbyname(3). host can be a domain name or the presentation format of an address.

Returns an array of information similar to that found in a struct hostent:

- cannonical name: the cannonical name for host in the DNS, or a
  string representing the address
- aliases: an array of aliases for the canonical name, there may be no aliases
- address family: usually one of Socket::AF_INET or Socket::AF_INET6
- address: a string, the binary value of the +struct sockaddr+ for this name, in
  the indicated address family
- ...: if there are multiple addresses for this host,  a series of
  strings/+struct sockaddr+s may follow, not all necessarily in the same
  address family. Note that the fact that they may not be all in the same
  address family is a departure from the behaviour of gethostbyname(3).

Note: I believe that the fact that the multiple addresses returned are not necessarily in the same address family may be a bug, since if this function actually called gethostbyname(3), ALL the addresses returned in the trailing address list (h_addr_list from struct hostent) would be of the same address family! Examples from my system, OS X 10.3:

["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
  and
["ensemble.local", [], 30, "\376\200\000\004\000\000\000\000\002\003\223\377\376\255\010\214", "\300\250{\232" ]

Similar information can be returned by Socket.getaddrinfo if called as:

Socket.getaddrinfo(+host+, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)

Examples

Socket.gethostbyname "example.com"
=> ["example.com", [], 2, "\300\000\"\246"]

This name has no DNS aliases, and a single IPv4 address.

Socket.gethostbyname "smtp.telus.net"
=> ["smtp.svc.telus.net", ["smtp.telus.net"], 2, "\307\271\334\371"]

This name is an an alias so the canonical name is returned, as well as the alias and a single IPv4 address.

Socket.gethostbyname "localhost"
=> ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]

This machine has no aliases, returns an IPv6 address, and has an additional IPv4 address.

host can also be an IP address in presentation format, in which case a reverse lookup is done on the address:

Socket.gethostbyname("127.0.0.1")
=> ["localhost", [], 2, "\177\000\000\001"]

Socket.gethostbyname("192.0.34.166")
=> ["www.example.com", [], 2, "\300\000\"\246"]

See

See: Socket.getaddrinfo



# File 'socket.c'

/*
 * Document-method: gethostbyname
 * call-seq: Socket.gethostbyname(host) => hostent
 *
 * Resolve +host+ and return name and address information for it, similarly to
 * gethostbyname(3). +host+ can be a domain name or the presentation format of
 * an address.
 *
 * Returns an array of information similar to that found in a +struct hostent+:
 *   - cannonical name: the cannonical name for host in the DNS, or a
 *     string representing the address
 *   - aliases: an array of aliases for the canonical name, there may be no aliases
 *   - address family: usually one of Socket::AF_INET or Socket::AF_INET6
 *   - address: a string, the binary value of the +struct sockaddr+ for this name, in
 *     the indicated address family
 *   - ...: if there are multiple addresses for this host,  a series of
 *     strings/+struct sockaddr+s may follow, not all necessarily in the same
 *     address family. Note that the fact that they may not be all in the same
 *     address family is a departure from the behaviour of gethostbyname(3).
 *
 * Note: I believe that the fact that the multiple addresses returned are not
 * necessarily in the same address family may be a bug, since if this function
 * actually called gethostbyname(3), ALL the addresses returned in the trailing
 * address list (h_addr_list from struct hostent) would be of the same address
 * family!  Examples from my system, OS X 10.3:
 *
 *   ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
 *     and
 *   ["ensemble.local", [], 30, "\376\200\000\004\000\000\000\000\002\003\223\377\376\255\010\214", "\300\250{\232" ]
 *
 * Similar information can be returned by Socket.getaddrinfo if called as:
 *
 *    Socket.getaddrinfo(+host+, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
 *
 * == Examples
 *   
 *   Socket.gethostbyname "example.com"                                                           
 *   => ["example.com", [], 2, "\300\000\"\246"]
 *   
 * This name has no DNS aliases, and a single IPv4 address.
 *   
 *   Socket.gethostbyname "smtp.telus.net"
 *   => ["smtp.svc.telus.net", ["smtp.telus.net"], 2, "\307\271\334\371"]
 *   
 * This name is an an alias so the canonical name is returned, as well as the
 * alias and a single IPv4 address.
 *   
 *   Socket.gethostbyname "localhost"
 *   => ["localhost", [], 30, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", "\177\000\000\001"]
 *   
 * This machine has no aliases, returns an IPv6 address, and has an additional IPv4 address.
 *
 * +host+ can also be an IP address in presentation format, in which case a
 * reverse lookup is done on the address:
 *
 *   Socket.gethostbyname("127.0.0.1")
 *   => ["localhost", [], 2, "\177\000\000\001"]
 *
 *   Socket.gethostbyname("192.0.34.166")
 *   => ["www.example.com", [], 2, "\300\000\"\246"]
 *
 *
 * == See
 * See: Socket.getaddrinfo
 */
static VALUE
sock_s_gethostbyname(obj, host)
    VALUE obj, host;
{
    rb_secure(3);
    return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
}

.gethostnameObject

.getnameinfoObject

.getservbyname(name, proto = "tcp") ⇒ Object

name is a service name (???ftp???, ???telnet???, ???) and proto is a protocol name (???udp???, ???tcp???, ???). ???/etc/services??? (or your system???s equivalent) is searched for a service for name and proto, and the port number is returned.

Note that unlike Socket.getaddrinfo, proto may not be specified using the Socket::SOCK_* constants, a string must must be used.



# File 'socket.c'

/*
 * Document-method: getservbyname
 * call-seq: Socket.getservbyname(name, proto="tcp") => port
 *
 * +name+ is a service name ("ftp", "telnet", ...) and proto is a protocol name
 * ("udp", "tcp", ...). '/etc/services' (or your system's equivalent) is
 * searched for a service for +name+ and +proto+, and the port number is
 * returned.
 *
 * Note that unlike Socket.getaddrinfo, +proto+ may not be specified using the
 * Socket::SOCK_* constants, a string must must be used.
 */
static VALUE
sock_s_getservbyaname(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE service, proto;
    struct servent *sp;
    int port;

    rb_scan_args(argc, argv, "11", &service, &proto);
    if (NIL_P(proto)) proto = rb_str_new2("tcp");
    StringValue(service);
    StringValue(proto);

    sp = getservbyname(StringValueCStr(service),  StringValueCStr(proto));
    if (sp) {
    port = ntohs(sp->s_port);
    }
    else {
    char *s = RSTRING(service)->ptr;
    char *end;

    port = strtoul(s, &end, 0);
    if (*end != '\0') {
        rb_raise(rb_eSocket, "no such service %s/%s", s, RSTRING(proto)->ptr);
    }
    }
    return INT2FIX(port);
}

.pack_sockaddr_inObject

.pack_sockaddr_unObject

.pairObject

.sockaddr_inObject

.sockaddr_unObject

.socketpairObject

.unpack_sockaddr_inObject

.unpack_sockaddr_unObject

Instance Method Details

#acceptArray

Accepts an incoming connection returning an array containing a new Socket object and a string holding the struct sockaddr information about the caller.

Example

# In one script, start this first
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 )
client, client_sockaddr = socket.accept
puts "The client said, '#{client.readline.chomp}'"
client.puts "Hello from script one!"
socket.close

# In another script, start this second
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
socket.connect( sockaddr )
socket.puts "Hello from script 2."
puts "The server said, '#{socket.readline.chomp}'"
socket.close

Unix-based Exceptions

On unix-based based systems the following system exceptions may be raised if the call to accept fails:

  • Errno::EAGAIN - O_NONBLOCK is set for the socket file descriptor and no connections are parent to be accepted

  • Errno::EWOULDBLOCK - same as Errno::EAGAIN

  • Errno::EBADF - the socket is not a valid file descriptor

  • Errno::ECONNABORTED - a connection has been aborted

  • Errno::EFAULT - the socket's internal address or address length parameter cannot be access or written

  • Errno::EINTR - the accept method was interrupted by a signal that was caught before a valid connection arrived

  • Errno::EINVAL - the socket is not accepting connections

  • Errno::EMFILE - OPEN_MAX file descriptors are currently open in the calling process

  • Errno::ENOBUFS - no buffer space is available

  • Errno::ENOMEM - there was insufficient memory available to complete the operation

  • Errno::ENOSR - there was insufficient STREAMS resources available to complete the operation

  • Errno::ENFILE - the maximum number of file descriptors in the system are already open

  • Errno::ENOTSOCK - the socket does not refer to a socket

  • Errno::EOPNOTSUPP - the socket type for the calling socket does not support accept connections

  • Errno::EPROTO - a protocol error has occurred

Windows Exceptions

On Windows systems the following system exceptions may be raised if the call to accept fails:

  • Errno::ECONNRESET - an incoming connection was indicated, but was terminated by the remote peer prior to accepting the connection

  • Errno::EFAULT - the socket's internal address or address length parameter is too small or is not a valid part of the user space address

  • Errno::EINVAL - the listen method was not invoked prior to calling accept

  • Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or the service provider is still processing a callback function

  • Errno::EMFILE - the queue is not empty, upong etry to accept and there are no socket descriptors available

  • Errno::ENETDOWN - the network is down

  • Errno::ENOBUFS - no buffer space is available

  • Errno::ENOTSOCK - socket is not a socket

  • Errno::EOPNOTSUPP - socket is not a type that supports connection-oriented service.

  • Errno::EWOULDBLOCK - socket is marked as nonblocking and no connections are present to be accepted

See

  • accept manual pages on unix-based systems

  • accept function in Microsoft's Winsock functions reference

Returns:

  • (Array)


# File 'socket.c'

/*
 * call-seq:
 *  socket.accept => [ socket, string ]
 * 
 * Accepts an incoming connection returning an array containing a new
 * Socket object and a string holding the +struct+ sockaddr information about 
 * the caller.
 * 
 * === Example
 *  # In one script, start this first
 *  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 )
 *  client, client_sockaddr = socket.accept
 *  puts "The client said, '#{client.readline.chomp}'"
 *  client.puts "Hello from script one!"
 *  socket.close
 * 
 *  # In another script, start this second
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
 *  sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
 *  socket.connect( sockaddr )
 *  socket.puts "Hello from script 2." 
 *  puts "The server said, '#{socket.readline.chomp}'"
 *  socket.close 
 * 
 * === Unix-based Exceptions
 * On unix-based based systems the following system exceptions may be raised if the
 * call to _accept_ fails:
 * * Errno::EAGAIN - O_NONBLOCK is set for the +socket+ file descriptor and no 
 *   connections are parent to be accepted
 * * Errno::EWOULDBLOCK - same as Errno::EAGAIN
 * * Errno::EBADF - the +socket+ is not a valid file descriptor
 * * Errno::ECONNABORTED - a connection has been aborted
 * * Errno::EFAULT - the socket's internal address or address length parameter 
 *   cannot be access or written
 * * Errno::EINTR - the _accept_ method was interrupted by a signal that was 
 *   caught before a valid connection arrived
 * * Errno::EINVAL - the +socket+ is not accepting connections
 * * Errno::EMFILE - OPEN_MAX file descriptors are currently open in the calling 
 *   process
 * * Errno::ENOBUFS - no buffer space is available
 * * Errno::ENOMEM - there was insufficient memory available to complete the
 *   operation
 * * Errno::ENOSR - there was insufficient STREAMS resources available to 
 *   complete the operation
 * * Errno::ENFILE - the maximum number of file descriptors in the system are 
 *   already open
 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
 * * Errno::EOPNOTSUPP - the socket type for the calling +socket+ does not 
 *   support accept connections
 * * Errno::EPROTO - a protocol error has occurred
 * 
 * === Windows Exceptions
 * On Windows systems the following system exceptions may be raised if 
 * the call to _accept_ fails:
 * * Errno::ECONNRESET - an incoming connection was indicated, but was 
 *   terminated by the remote peer prior to accepting the connection
 * * Errno::EFAULT - the socket's internal address or address length parameter
 *   is too small or is not a valid part of the user space address
 * * Errno::EINVAL - the _listen_ method was not invoked prior to calling _accept_
 * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or
 *   the service provider is still processing a callback function
 * * Errno::EMFILE - the queue is not empty, upong etry to _accept_ and there are
 *   no socket descriptors available
 * * Errno::ENETDOWN - the network is down
 * * Errno::ENOBUFS - no buffer space is available
 * * Errno::ENOTSOCK - +socket+ is not a socket
 * * Errno::EOPNOTSUPP - +socket+ is not a type that supports connection-oriented
 *   service.
 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and no connections are
 *   present to be accepted
 * 
 * === See
 * * accept manual pages on unix-based systems
 * * accept function in Microsoft's Winsock functions reference
 */
static VALUE
sock_accept(sock)
    VALUE sock;
{
    OpenFile *fptr;
    VALUE sock2;
    char buf[1024];
    socklen_t len = sizeof buf;

    GetOpenFile(sock, fptr);
    sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);

    return rb_assoc_new(sock2, rb_str_new(buf, len));
}

#accept_nonblockArray

Accepts an incoming connection using accept(2) after O_NONBLOCK is set for the underlying file descriptor. It returns an array containg the accpeted socket for the incoming connection, client_socket, and a string that contains the struct sockaddr information about the caller, client_sockaddr.

Example

# In one script, start this first
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.bind(sockaddr)
socket.listen(5)
begin
  client_socket, client_sockaddr = socket.accept_nonblock
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
  IO.select([socket])
  retry
end
puts "The client said, '#{client_socket.readline.chomp}'"
client_socket.puts "Hello from script one!"
socket.close

# In another script, start this second
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.connect(sockaddr)
socket.puts "Hello from script 2."
puts "The server said, '#{socket.readline.chomp}'"
socket.close

Refer to Socket#accept for the exceptions that may be thrown if the call to accept_nonblock fails.

Socket#accept_nonblock may raise any error corresponding to accept(2) failure, including Errno::EAGAIN.

See

  • Socket#accept

Returns:

  • (Array)


# File 'socket.c'

/*
 * call-seq:
 *    socket.accept_nonblock => [client_socket, client_sockaddr]
 * 
 * Accepts an incoming connection using accept(2) after
 * O_NONBLOCK is set for the underlying file descriptor.
 * It returns an array containg the accpeted socket
 * for the incoming connection, _client_socket_,
 * and a string that contains the +struct+ sockaddr information
 * about the caller, _client_sockaddr_.
 * 
 * === Example
 *  # In one script, start this first
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new(AF_INET, SOCK_STREAM, 0)
 *  sockaddr = Socket.sockaddr_in(2200, 'localhost')
 *  socket.bind(sockaddr)
 *  socket.listen(5)
 *  begin
 *    client_socket, client_sockaddr = socket.accept_nonblock
 *  rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
 *    IO.select([socket])
 *    retry
 *  end
 *  puts "The client said, '#{client_socket.readline.chomp}'"
 *  client_socket.puts "Hello from script one!"
 *  socket.close
 *
 *  # In another script, start this second
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new(AF_INET, SOCK_STREAM, 0)
 *  sockaddr = Socket.sockaddr_in(2200, 'localhost')
 *  socket.connect(sockaddr)
 *  socket.puts "Hello from script 2." 
 *  puts "The server said, '#{socket.readline.chomp}'"
 *  socket.close
 * 
 * Refer to Socket#accept for the exceptions that may be thrown if the call
 * to _accept_nonblock_ fails. 
 *
 * Socket#accept_nonblock may raise any error corresponding to accept(2) failure,
 * including Errno::EAGAIN.
 * 
 * === See
 * * Socket#accept
 */
static VALUE
sock_accept_nonblock(sock)
    VALUE sock;
{
    OpenFile *fptr;
    VALUE sock2;
    char buf[1024];
    socklen_t len = sizeof buf;

    GetOpenFile(sock, fptr);
    sock2 = s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf, &len);
    return rb_assoc_new(sock2, rb_str_new(buf, len));
}

#bind(server_sockaddr) ⇒ 0

Binds to the given struct sockaddr.

Parameter

  • server_sockaddr - the struct sockaddr contained in a string

Example

require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
socket.bind( sockaddr )

Unix-based Exceptions

On unix-based based systems the following system exceptions may be raised if the call to bind fails:

  • Errno::EACCES - the specified sockaddr is protected and the current user does not have permission to bind to it

  • Errno::EADDRINUSE - the specified sockaddr is already in use

  • Errno::EADDRNOTAVAIL - the specified sockaddr is not available from the local machine

  • Errno::EAFNOSUPPORT - the specified sockaddr isnot a valid address for the family of the calling socket

  • Errno::EBADF - the sockaddr specified is not a valid file descriptor

  • Errno::EFAULT - the sockaddr argument cannot be accessed

  • Errno::EINVAL - the socket is already bound to an address, and the protocol does not support binding to the new sockaddr or the socket has been shut down.

  • Errno::EINVAL - the address length is not a valid length for the address family

  • Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded PATH_MAX

  • Errno::ENOBUFS - no buffer space is available

  • Errno::ENOSR - there were insufficient STREAMS resources available to complete the operation

  • Errno::ENOTSOCK - the socket does not refer to a socket

  • Errno::EOPNOTSUPP - the socket type of the socket does not support binding to an address

On unix-based based systems if the address family of the calling socket is Socket::AF_UNIX the follow exceptions may be raised if the call to bind fails:

  • Errno::EACCES - search permission is denied for a component of the prefix path or write access to the socket is denided

  • Errno::EDESTADDRREQ - the sockaddr argument is a null pointer

  • Errno::EISDIR - same as Errno::EDESTADDRREQ

  • Errno::EIO - an i/o error occurred

  • Errno::ELOOP - too many symbolic links were encountered in translating the pathname in sockaddr

  • Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX characters, or an entired pathname exceeded PATH_MAX characters

  • Errno::ENOENT - a component of the pathname does not name an existing file or the pathname is an empty string

  • Errno::ENOTDIR - a component of the path prefix of the pathname in sockaddr is not a directory

  • Errno::EROFS - the name would reside on a read only filesystem

Windows Exceptions

On Windows systems the following system exceptions may be raised if the call to bind fails:

  • Errno::ENETDOWN-- the network is down

  • Errno::EACCES - the attempt to connect the datagram socket to the broadcast address failed

  • Errno::EADDRINUSE - the socket's local address is already in use

  • Errno::EADDRNOTAVAIL - the specified address is not a valid address for this computer

  • Errno::EFAULT - the socket's internal address or address length parameter is too small or is not a valid part of the user space addressed

  • Errno::EINVAL - the socket is already bound to an address

  • Errno::ENOBUFS - no buffer space is available

  • Errno::ENOTSOCK - the socket argument does not refer to a socket

See

  • bind manual pages on unix-based systems

  • bind function in Microsoft's Winsock functions reference

Returns:

  • (0)


# File 'socket.c'

/*
 * call-seq:
 *  socket.bind(server_sockaddr) => 0
 * 
 * Binds to the given +struct+ sockaddr.
 * 
 * === Parameter
 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
 *
 * === Example
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
 *  sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
 *  socket.bind( sockaddr )
 *  
 * === Unix-based Exceptions
 * On unix-based based systems the following system exceptions may be raised if 
 * the call to _bind_ fails:
 * * Errno::EACCES - the specified _sockaddr_ is protected and the current
 *   user does not have permission to bind to it
 * * Errno::EADDRINUSE - the specified _sockaddr_ is already in use
 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
 *   local machine
 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ isnot a valid address for
 *   the family of the calling +socket+
 * * Errno::EBADF - the _sockaddr_ specified is not a valid file descriptor
 * * Errno::EFAULT - the _sockaddr_ argument cannot be accessed
 * * Errno::EINVAL - the +socket+ is already bound to an address, and the 
 *   protocol does not support binding to the new _sockaddr_ or the +socket+
 *   has been shut down.
 * * Errno::EINVAL - the address length is not a valid length for the address
 *   family
 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
 *   PATH_MAX
 * * Errno::ENOBUFS - no buffer space is available
 * * Errno::ENOSR - there were insufficient STREAMS resources available to 
 *   complete the operation
 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
 * * Errno::EOPNOTSUPP - the socket type of the +socket+ does not support 
 *   binding to an address
 * 
 * On unix-based based systems if the address family of the calling +socket+ is
 * Socket::AF_UNIX the follow exceptions may be raised if the call to _bind_
 * fails:
 * * Errno::EACCES - search permission is denied for a component of the prefix
 *   path or write access to the +socket+ is denided
 * * Errno::EDESTADDRREQ - the _sockaddr_ argument is a null pointer
 * * Errno::EISDIR - same as Errno::EDESTADDRREQ
 * * Errno::EIO - an i/o error occurred
 * * Errno::ELOOP - too many symbolic links were encountered in translating
 *   the pathname in _sockaddr_
 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX 
 *   characters, or an entired pathname exceeded PATH_MAX characters
 * * Errno::ENOENT - a component of the pathname does not name an existing file
 *   or the pathname is an empty string
 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
 *   is not a directory
 * * Errno::EROFS - the name would reside on a read only filesystem
 * 
 * === Windows Exceptions
 * On Windows systems the following system exceptions may be raised if 
 * the call to _bind_ fails:
 * * Errno::ENETDOWN-- the network is down
 * * Errno::EACCES - the attempt to connect the datagram socket to the 
 *   broadcast address failed
 * * Errno::EADDRINUSE - the socket's local address is already in use
 * * Errno::EADDRNOTAVAIL - the specified address is not a valid address for this
 *   computer
 * * Errno::EFAULT - the socket's internal address or address length parameter
 *   is too small or is not a valid part of the user space addressed
 * * Errno::EINVAL - the +socket+ is already bound to an address
 * * Errno::ENOBUFS - no buffer space is available
 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
 * 
 * === See
 * * bind manual pages on unix-based systems
 * * bind function in Microsoft's Winsock functions reference
 */ 
static VALUE
sock_bind(sock, addr)
    VALUE sock, addr;
{
    OpenFile *fptr;

    StringValue(addr);
    GetOpenFile(sock, fptr);
    if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
    rb_sys_fail("bind(2)");

    return INT2FIX(0);
}

#connect(server_sockaddr) ⇒ 0

Requests a connection to be made on the given server_sockaddr. Returns 0 if successful, otherwise an exception is raised.

Parameter

  • server_sockaddr - the struct sockaddr contained in a string

Example:

# Pull down Google's web page
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
socket.connect( sockaddr )
socket.write( "GET / HTTP/1.0\r\n\r\n" )
results = socket.read

Unix-based Exceptions

On unix-based systems the following system exceptions may be raised if the call to connect fails:

  • Errno::EACCES - search permission is denied for a component of the prefix path or write access to the socket is denided

  • Errno::EADDRINUSE - the sockaddr is already in use

  • Errno::EADDRNOTAVAIL - the specified sockaddr is not available from the local machine

  • Errno::EAFNOSUPPORT - the specified sockaddr is not a valid address for the address family of the specified socket

  • Errno::EALREADY - a connection is already in progress for the specified socket

  • Errno::EBADF - the socket is not a valid file descriptor

  • Errno::ECONNREFUSED - the target sockaddr was not listening for connections refused the connection request

  • Errno::ECONNRESET - the remote host reset the connection request

  • Errno::EFAULT - the sockaddr cannot be accessed

  • Errno::EHOSTUNREACH - the destination host cannot be reached (probably because the host is down or a remote router cannot reach it)

  • Errno::EINPROGRESS - the O_NONBLOCK is set for the socket and the connection cnanot be immediately established; the connection will be established asynchronously

  • Errno::EINTR - the attempt to establish the connection was interrupted by delivery of a signal that was caught; the connection will be established asynchronously

  • Errno::EISCONN - the specified socket is already connected

  • Errno::EINVAL - the address length used for the sockaddr is not a valid length for the address family or there is an invalid family in sockaddr

  • Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded PATH_MAX

  • Errno::ENETDOWN - the local interface used to reach the destination is down

  • Errno::ENETUNREACH - no route to the network is present

  • Errno::ENOBUFS - no buffer space is available

  • Errno::ENOSR - there were insufficient STREAMS resources available to complete the operation

  • Errno::ENOTSOCK - the socket argument does not refer to a socket

  • Errno::EOPNOTSUPP - the calling socket is listening and cannot be connected

  • Errno::EPROTOTYPE - the sockaddr has a different type than the socket bound to the specified peer address

  • Errno::ETIMEDOUT - the attempt to connect time out before a connection was made.

On unix-based systems if the address family of the calling socket is AF_UNIX the follow exceptions may be raised if the call to connect fails:

  • Errno::EIO - an i/o error occured while reading from or writing to the file system

  • Errno::ELOOP - too many symbolic links were encountered in translating the pathname in sockaddr

  • Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX characters, or an entired pathname exceeded PATH_MAX characters

  • Errno::ENOENT - a component of the pathname does not name an existing file or the pathname is an empty string

  • Errno::ENOTDIR - a component of the path prefix of the pathname in sockaddr is not a directory

Windows Exceptions

On Windows systems the following system exceptions may be raised if the call to connect fails:

  • Errno::ENETDOWN - the network is down

  • Errno::EADDRINUSE - the socket's local address is already in use

  • Errno::EINTR - the socket was cancelled

  • Errno::EINPROGRESS - a blocking socket is in progress or the service provider is still processing a callback function. Or a nonblocking connect call is in progress on the socket.

  • Errno::EALREADY - see Errno::EINVAL

  • Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as ADDR_ANY TODO check ADDRANY TO INADDR_ANY

  • Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with with this socket

  • Errno::ECONNREFUSED - the target sockaddr was not listening for connections refused the connection request

  • Errno::EFAULT - the socket's internal address or address length parameter is too small or is not a valid part of the user space address

  • Errno::EINVAL - the socket is a listening socket

  • Errno::EISCONN - the socket is already connected

  • Errno::ENETUNREACH - the network cannot be reached from this host at this time

  • Errno::EHOSTUNREACH - no route to the network is present

  • Errno::ENOBUFS - no buffer space is available

  • Errno::ENOTSOCK - the socket argument does not refer to a socket

  • Errno::ETIMEDOUT - the attempt to connect time out before a connection was made.

  • Errno::EWOULDBLOCK - the socket is marked as nonblocking and the connection cannot be completed immediately

  • Errno::EACCES - the attempt to connect the datagram socket to the broadcast address failed

See

  • connect manual pages on unix-based systems

  • connect function in Microsoft's Winsock functions reference

Returns:

  • (0)


# File 'socket.c'

/*
 * call-seq:
 *  socket.connect(server_sockaddr) => 0
 * 
 * Requests a connection to be made on the given +server_sockaddr+. Returns 0 if
 * successful, otherwise an exception is raised.
 *  
 * === Parameter
 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
 * 
 * === Example:
 *  # Pull down Google's web page
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
 *  sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
 *  socket.connect( sockaddr )
 *  socket.write( "GET / HTTP/1.0\r\n\r\n" )
 *  results = socket.read 
 * 
 * === Unix-based Exceptions
 * On unix-based systems the following system exceptions may be raised if 
 * the call to _connect_ fails:
 * * Errno::EACCES - search permission is denied for a component of the prefix
 *   path or write access to the +socket+ is denided
 * * Errno::EADDRINUSE - the _sockaddr_ is already in use
 * * Errno::EADDRNOTAVAIL - the specified _sockaddr_ is not available from the
 *   local machine
 * * Errno::EAFNOSUPPORT - the specified _sockaddr_ is not a valid address for 
 *   the address family of the specified +socket+
 * * Errno::EALREADY - a connection is already in progress for the specified
 *   socket
 * * Errno::EBADF - the +socket+ is not a valid file descriptor
 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
 *   refused the connection request
 * * Errno::ECONNRESET - the remote host reset the connection request
 * * Errno::EFAULT - the _sockaddr_ cannot be accessed
 * * Errno::EHOSTUNREACH - the destination host cannot be reached (probably 
 *   because the host is down or a remote router cannot reach it)
 * * Errno::EINPROGRESS - the O_NONBLOCK is set for the +socket+ and the
 *   connection cnanot be immediately established; the connection will be
 *   established asynchronously
 * * Errno::EINTR - the attempt to establish the connection was interrupted by
 *   delivery of a signal that was caught; the connection will be established
 *   asynchronously
 * * Errno::EISCONN - the specified +socket+ is already connected
 * * Errno::EINVAL - the address length used for the _sockaddr_ is not a valid
 *   length for the address family or there is an invalid family in _sockaddr_ 
 * * Errno::ENAMETOOLONG - the pathname resolved had a length which exceeded
 *   PATH_MAX
 * * Errno::ENETDOWN - the local interface used to reach the destination is down
 * * Errno::ENETUNREACH - no route to the network is present
 * * Errno::ENOBUFS - no buffer space is available
 * * Errno::ENOSR - there were insufficient STREAMS resources available to 
 *   complete the operation
 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
 * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected
 * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket 
 *   bound to the specified peer address
 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
 *   was made.
 * 
 * On unix-based systems if the address family of the calling +socket+ is
 * AF_UNIX the follow exceptions may be raised if the call to _connect_
 * fails:
 * * Errno::EIO - an i/o error occured while reading from or writing to the 
 *   file system
 * * Errno::ELOOP - too many symbolic links were encountered in translating
 *   the pathname in _sockaddr_
 * * Errno::ENAMETOOLLONG - a component of a pathname exceeded NAME_MAX 
 *   characters, or an entired pathname exceeded PATH_MAX characters
 * * Errno::ENOENT - a component of the pathname does not name an existing file
 *   or the pathname is an empty string
 * * Errno::ENOTDIR - a component of the path prefix of the pathname in _sockaddr_
 *   is not a directory 
 * 
 * === Windows Exceptions
 * On Windows systems the following system exceptions may be raised if 
 * the call to _connect_ fails:
 * * Errno::ENETDOWN - the network is down
 * * Errno::EADDRINUSE - the socket's local address is already in use
 * * Errno::EINTR - the socket was cancelled
 * * Errno::EINPROGRESS - a blocking socket is in progress or the service provider
 *   is still processing a callback function. Or a nonblocking connect call is 
 *   in progress on the +socket+.
 * * Errno::EALREADY - see Errno::EINVAL
 * * Errno::EADDRNOTAVAIL - the remote address is not a valid address, such as 
 *   ADDR_ANY TODO check ADDRANY TO INADDR_ANY
 * * Errno::EAFNOSUPPORT - addresses in the specified family cannot be used with
 *   with this +socket+
 * * Errno::ECONNREFUSED - the target _sockaddr_ was not listening for connections
 *   refused the connection request
 * * Errno::EFAULT - the socket's internal address or address length parameter
 *   is too small or is not a valid part of the user space address
 * * Errno::EINVAL - the +socket+ is a listening socket
 * * Errno::EISCONN - the +socket+ is already connected
 * * Errno::ENETUNREACH - the network cannot be reached from this host at this time
 * * Errno::EHOSTUNREACH - no route to the network is present
 * * Errno::ENOBUFS - no buffer space is available
 * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket
 * * Errno::ETIMEDOUT - the attempt to connect time out before a connection
 *   was made.
 * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the 
 *   connection cannot be completed immediately
 * * Errno::EACCES - the attempt to connect the datagram socket to the 
 *   broadcast address failed
 * 
 * === See
 * * connect manual pages on unix-based systems
 * * connect function in Microsoft's Winsock functions reference
 */
static VALUE
sock_connect(sock, addr)
    VALUE sock, addr;
{
    OpenFile *fptr;
    int fd;

    StringValue(addr);
    addr = rb_str_new4(addr);
    GetOpenFile(sock, fptr);
    fd = fileno(fptr->f);
    if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
    rb_sys_fail("connect(2)");
    }

    return INT2FIX(0);
}

#connect_nonblock(server_sockaddr) ⇒ 0

Requests a connection to be made on the given server_sockaddr after O_NONBLOCK is set for the underlying file descriptor. Returns 0 if successful, otherwise an exception is raised.

Parameter

  • server_sockaddr - the struct sockaddr contained in a string

Example:

# Pull down Google's web page
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, 'www.google.com')
begin
  socket.connect_nonblock(sockaddr)
rescue Errno::EINPROGRESS
  IO.select(nil, [socket])
  begin
    socket.connect_nonblock(sockaddr)
  rescue Errno::EISCONN
  end
end
socket.write("GET / HTTP/1.0\r\n\r\n")
results = socket.read

Refer to Socket#connect for the exceptions that may be thrown if the call to connect_nonblock fails.

Socket#connect_nonblock may raise any error corresponding to connect(2) failure, including Errno::EINPROGRESS.

See

  • Socket#connect

Returns:

  • (0)


# File 'socket.c'

/*
 * call-seq:
 *  socket.connect_nonblock(server_sockaddr) => 0
 * 
 * Requests a connection to be made on the given +server_sockaddr+ after
 * O_NONBLOCK is set for the underlying file descriptor.
 * Returns 0 if successful, otherwise an exception is raised.
 *  
 * === Parameter
 * * +server_sockaddr+ - the +struct+ sockaddr contained in a string
 * 
 * === Example:
 *  # Pull down Google's web page
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new(AF_INET, SOCK_STREAM, 0)
 *  sockaddr = Socket.sockaddr_in(80, 'www.google.com')
 *  begin
 *    socket.connect_nonblock(sockaddr)
 *  rescue Errno::EINPROGRESS
 *    IO.select(nil, [socket])
 *    begin
 *      socket.connect_nonblock(sockaddr)
 *    rescue Errno::EISCONN
 *    end
 *  end
 *  socket.write("GET / HTTP/1.0\r\n\r\n")
 *  results = socket.read 
 * 
 * Refer to Socket#connect for the exceptions that may be thrown if the call
 * to _connect_nonblock_ fails. 
 *
 * Socket#connect_nonblock may raise any error corresponding to connect(2) failure,
 * including Errno::EINPROGRESS.
 *
 * === See
 * * Socket#connect
 */
static VALUE
sock_connect_nonblock(sock, addr)
    VALUE sock, addr;
{
    OpenFile *fptr;
    int n;

    StringValue(addr);
    addr = rb_str_new4(addr);
    GetOpenFile(sock, fptr);
    rb_io_set_nonblock(fptr);
    n = connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len);
    if (n < 0) {
    rb_sys_fail("connect(2)");
    }

    return INT2FIX(n);
}

#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

Returns:

  • (0)


# File 'socket.c'

/*
 * 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;
{
    OpenFile *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);
}

#recvfrom(maxlen) ⇒ Array #recvfrom(maxlen, flags) ⇒ Array

Receives up to maxlen bytes from socket. flags is zero or more of the MSG_ options. The first element of the results, mesg, is the data received. The second element, sender_sockaddr, contains protocol-specific information on the sender.

Parameters

  • maxlen - the number of bytes to receive from the socket

  • flags - zero or more of the MSG_ options

Example

# In one file, start this first
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 )
client, client_sockaddr = socket.accept
data = client.recvfrom( 20 )[0].chomp
puts "I only received 20 bytes '#{data}'"
sleep 1
socket.close

# In another file, start this second
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
socket.connect( sockaddr )
socket.puts "Watch this get cut short!"
socket.close

Unix-based Exceptions

On unix-based based systems the following system exceptions may be raised if the call to recvfrom fails:

  • Errno::EAGAIN - the socket file descriptor is marked as O_NONBLOCK and no data is waiting to be received; or MSG_OOB is set and no out-of-band data is available and either the socket file descriptor is marked as O_NONBLOCK or the socket does not support blocking to wait for out-of-band-data

  • Errno::EWOULDBLOCK - see Errno::EAGAIN

  • Errno::EBADF - the socket is not a valid file descriptor

  • Errno::ECONNRESET - a connection was forcibly closed by a peer

  • Errno::EFAULT - the socket's internal buffer, address or address length cannot be accessed or written

  • Errno::EINTR - a signal interupted recvfrom before any data was available

  • Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available

  • Errno::EIO - an i/o error occurred while reading from or writing to the filesystem

  • Errno::ENOBUFS - insufficient resources were available in the system to perform the operation

  • Errno::ENOMEM - insufficient memory was available to fulfill the request

  • Errno::ENOSR - there were insufficient STREAMS resources available to complete the operation

  • Errno::ENOTCONN - a receive is attempted on a connection-mode socket that is not connected

  • Errno::ENOTSOCK - the socket does not refer to a socket

  • Errno::EOPNOTSUPP - the specified flags are not supported for this socket type

  • Errno::ETIMEDOUT - the connection timed out during connection establishment or due to a transmission timeout on an active connection

Windows Exceptions

On Windows systems the following system exceptions may be raised if the call to recvfrom fails:

  • Errno::ENETDOWN - the network is down

  • Errno::EFAULT - the internal buffer and from parameters on socket are not part of the user address space, or the internal fromlen parameter is too small to accomodate the peer address

  • Errno::EINTR - the (blocking) call was cancelled by an internal call to the WinSock function WSACancelBlockingCall

  • Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or the service provider is still processing a callback function

  • Errno::EINVAL - socket has not been bound with a call to bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal len parameter on socket was zero or negative

  • Errno::EISCONN - socket is already connected. The call to recvfrom is not permitted with a connected socket on a socket that is connetion oriented or connectionless.

  • Errno::ENETRESET - the connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress.

  • Errno::EOPNOTSUPP - MSG_OOB was specified, but socket is not stream-style such as type SOCK_STREAM. OOB data is not supported in the communication domain associated with socket, or socket is unidirectional and supports only send operations

  • Errno::ESHUTDOWN - socket has been shutdown. It is not possible to call recvfrom on a socket after shutdown has been invoked.

  • Errno::EWOULDBLOCK - socket is marked as nonblocking and a call to recvfrom would block.

  • Errno::EMSGSIZE - the message was too large to fit into the specified buffer and was truncated.

  • Errno::ETIMEDOUT - the connection has been dropped, because of a network failure or because the system on the other end went down without notice

  • Errno::ECONNRESET - the virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.

Overloads:

  • #recvfrom(maxlen) ⇒ Array

    Returns:

    • (Array)
  • #recvfrom(maxlen, flags) ⇒ Array

    Returns:

    • (Array)


# File 'socket.c'

/*
 * call-seq:
 *  socket.recvfrom(maxlen) => [mesg, sender_sockaddr]
 *  socket.recvfrom(maxlen, flags) => [mesg, sender_sockaddr]
 * 
 * Receives up to _maxlen_ bytes from +socket+. _flags_ is zero or more
 * of the +MSG_+ options. The first element of the results, _mesg_, is the data
 * received. The second element, _sender_sockaddr_, contains protocol-specific information
 * on the sender.
 * 
 * === Parameters
 * * +maxlen+ - the number of bytes to receive from the socket
 * * +flags+ - zero or more of the +MSG_+ options 
 * 
 * === Example
 *  # In one file, start this first
 *  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 )
 *  client, client_sockaddr = socket.accept
 *  data = client.recvfrom( 20 )[0].chomp
 *  puts "I only received 20 bytes '#{data}'"
 *  sleep 1
 *  socket.close
 * 
 *  # In another file, start this second
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
 *  sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
 *  socket.connect( sockaddr )
 *  socket.puts "Watch this get cut short!"
 *  socket.close 
 * 
 * === Unix-based Exceptions
 * On unix-based based systems the following system exceptions may be raised if the
 * call to _recvfrom_ fails:
 * * Errno::EAGAIN - the +socket+ file descriptor is marked as O_NONBLOCK and no
 *   data is waiting to be received; or MSG_OOB is set and no out-of-band data
 *   is available and either the +socket+ file descriptor is marked as 
 *   O_NONBLOCK or the +socket+ does not support blocking to wait for 
 *   out-of-band-data
 * * Errno::EWOULDBLOCK - see Errno::EAGAIN
 * * Errno::EBADF - the +socket+ is not a valid file descriptor
 * * Errno::ECONNRESET - a connection was forcibly closed by a peer
 * * Errno::EFAULT - the socket's internal buffer, address or address length 
 *   cannot be accessed or written
 * * Errno::EINTR - a signal interupted _recvfrom_ before any data was available
 * * Errno::EINVAL - the MSG_OOB flag is set and no out-of-band data is available
 * * Errno::EIO - an i/o error occurred while reading from or writing to the 
 *   filesystem
 * * Errno::ENOBUFS - insufficient resources were available in the system to 
 *   perform the operation
 * * Errno::ENOMEM - insufficient memory was available to fulfill the request
 * * Errno::ENOSR - there were insufficient STREAMS resources available to 
 *   complete the operation
 * * Errno::ENOTCONN - a receive is attempted on a connection-mode socket that
 *   is not connected
 * * Errno::ENOTSOCK - the +socket+ does not refer to a socket
 * * Errno::EOPNOTSUPP - the specified flags are not supported for this socket type
 * * Errno::ETIMEDOUT - the connection timed out during connection establishment
 *   or due to a transmission timeout on an active connection
 * 
 * === Windows Exceptions
 * On Windows systems the following system exceptions may be raised if 
 * the call to _recvfrom_ fails:
 * * Errno::ENETDOWN - the network is down
 * * Errno::EFAULT - the internal buffer and from parameters on +socket+ are not
 *   part of the user address space, or the internal fromlen parameter is
 *   too small to accomodate the peer address
 * * Errno::EINTR - the (blocking) call was cancelled by an internal call to
 *   the WinSock function WSACancelBlockingCall
 * * Errno::EINPROGRESS - a blocking Windows Sockets 1.1 call is in progress or 
 *   the service provider is still processing a callback function
 * * Errno::EINVAL - +socket+ has not been bound with a call to _bind_, or an
 *   unknown flag was specified, or MSG_OOB was specified for a socket with
 *   SO_OOBINLINE enabled, or (for byte stream-style sockets only) the internal
 *   len parameter on +socket+ was zero or negative
 * * Errno::EISCONN - +socket+ is already connected. The call to _recvfrom_ is
 *   not permitted with a connected socket on a socket that is connetion 
 *   oriented or connectionless.
 * * Errno::ENETRESET - the connection has been broken due to the keep-alive 
 *   activity detecting a failure while the operation was in progress.
 * * Errno::EOPNOTSUPP - MSG_OOB was specified, but +socket+ is not stream-style
 *   such as type SOCK_STREAM. OOB data is not supported in the communication
 *   domain associated with +socket+, or +socket+ is unidirectional and 
 *   supports only send operations
 * * Errno::ESHUTDOWN - +socket+ has been shutdown. It is not possible to 
 *   call _recvfrom_ on a socket after _shutdown_ has been invoked.
 * * Errno::EWOULDBLOCK - +socket+ is marked as nonblocking and a  call to 
 *   _recvfrom_ would block.
 * * Errno::EMSGSIZE - the message was too large to fit into the specified buffer
 *   and was truncated.
 * * Errno::ETIMEDOUT - the connection has been dropped, because of a network
 *   failure or because the system on the other end went down without
 *   notice
 * * Errno::ECONNRESET - the virtual circuit was reset by the remote side 
 *   executing a hard or abortive close. The application should close the
 *   socket; it is no longer usable. On a UDP-datagram socket this error
 *   indicates a previous send operation resulted in an ICMP Port Unreachable
 *   message.
 */
static VALUE
sock_recvfrom(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    return s_recvfrom(sock, argc, argv, RECV_SOCKET);
}

#recvfrom_nonblock(maxlen) ⇒ Array #recvfrom_nonblock(maxlen, flags) ⇒ Array

Receives up to maxlen bytes from socket using recvfrom(2) after O_NONBLOCK is set for the underlying file descriptor. flags is zero or more of the MSG_ options. The first element of the results, mesg, is the data received. The second element, sender_sockaddr, contains protocol-specific information on the sender.

When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns an empty string as data. The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.

Parameters

  • maxlen - the number of bytes to receive from the socket

  • flags - zero or more of the MSG_ options

Example

# In one file, start this first
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.bind(sockaddr)
socket.listen(5)
client, client_sockaddr = socket.accept
begin
  pair = client.recvfrom_nonblock(20)
rescue Errno::EAGAIN
  IO.select([client])
  retry
end
data = pair[0].chomp
puts "I only received 20 bytes '#{data}'"
sleep 1
socket.close

# In another file, start this second
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.connect(sockaddr)
socket.puts "Watch this get cut short!"
socket.close

Refer to Socket#recvfrom for the exceptions that may be thrown if the call to recvfrom_nonblock fails.

Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure, including Errno::EAGAIN.

See

  • Socket#recvfrom

Overloads:

  • #recvfrom_nonblock(maxlen) ⇒ Array

    Returns:

    • (Array)
  • #recvfrom_nonblock(maxlen, flags) ⇒ Array

    Returns:

    • (Array)


# File 'socket.c'

/*
 * call-seq:
 *  socket.recvfrom_nonblock(maxlen) => [mesg, sender_sockaddr]
 *  socket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_sockaddr]
 * 
 * Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
 * O_NONBLOCK is set for the underlying file descriptor.
 * _flags_ is zero or more of the +MSG_+ options.
 * The first element of the results, _mesg_, is the data received.
 * The second element, _sender_sockaddr_, contains protocol-specific information
 * on the sender.
 *
 * When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns
 * an empty string as data.
 * The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
 * 
 * === Parameters
 * * +maxlen+ - the number of bytes to receive from the socket
 * * +flags+ - zero or more of the +MSG_+ options 
 * 
 * === Example
 *  # In one file, start this first
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new(AF_INET, SOCK_STREAM, 0)
 *  sockaddr = Socket.sockaddr_in(2200, 'localhost')
 *  socket.bind(sockaddr)
 *  socket.listen(5)
 *  client, client_sockaddr = socket.accept
 *  begin
 *    pair = client.recvfrom_nonblock(20)
 *  rescue Errno::EAGAIN
 *    IO.select([client])
 *    retry
 *  end
 *  data = pair[0].chomp
 *  puts "I only received 20 bytes '#{data}'"
 *  sleep 1
 *  socket.close
 * 
 *  # In another file, start this second
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new(AF_INET, SOCK_STREAM, 0)
 *  sockaddr = Socket.sockaddr_in(2200, 'localhost')
 *  socket.connect(sockaddr)
 *  socket.puts "Watch this get cut short!"
 *  socket.close 
 * 
 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
 * to _recvfrom_nonblock_ fails. 
 *
 * Socket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
 * including Errno::EAGAIN.
 *
 * === See
 * * Socket#recvfrom
 */
static VALUE
sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
{
    return s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
}

#sysacceptArray

Accepts an incoming connection returnings an array containg the (integer) file descriptor for the incoming connection, client_socket_fd, and a string that contains the struct sockaddr information about the caller, client_sockaddr.

Example

# In one script, start this first
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 )
client_fd, client_sockaddr = socket.sysaccept
client_socket = Socket.for_fd( client_fd )
puts "The client said, '#{client_socket.readline.chomp}'"
client_socket.puts "Hello from script one!"
socket.close

# In another script, start this second
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
socket.connect( sockaddr )
socket.puts "Hello from script 2."
puts "The server said, '#{socket.readline.chomp}'"
socket.close

Refer to Socket#accept for the exceptions that may be thrown if the call to sysaccept fails.

See

  • Socket#accept

Returns:

  • (Array)


# File 'socket.c'

/*
 * call-seq:
 *  socket.sysaccept => [client_socket_fd, client_sockaddr]
 * 
 * Accepts an incoming connection returnings an array containg the (integer)
 * file descriptor for the incoming connection, _client_socket_fd_,
 * and a string that contains the +struct+ sockaddr information
 * about the caller, _client_sockaddr_.
 * 
 * === Example
 *  # In one script, start this first
 *  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 )
 *  client_fd, client_sockaddr = socket.sysaccept
 *  client_socket = Socket.for_fd( client_fd )
 *  puts "The client said, '#{client_socket.readline.chomp}'"
 *  client_socket.puts "Hello from script one!"
 *  socket.close
 * 
 *  # In another script, start this second
 *  require 'socket'
 *  include Socket::Constants
 *  socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
 *  sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' )
 *  socket.connect( sockaddr )
 *  socket.puts "Hello from script 2." 
 *  puts "The server said, '#{socket.readline.chomp}'"
 *  socket.close
 * 
 * Refer to Socket#accept for the exceptions that may be thrown if the call
 * to _sysaccept_ fails. 
 * 
 * === See
 * * Socket#accept
 */
static VALUE
sock_sysaccept(sock)
    VALUE sock;
{
    OpenFile *fptr;
    VALUE sock2;
    char buf[1024];
    socklen_t len = sizeof buf;

    GetOpenFile(sock, fptr);
    sock2 = s_accept(0,fileno(fptr->f),(struct sockaddr*)buf,&len);

    return rb_assoc_new(sock2, rb_str_new(buf, len));
}