# class BasicSocket

`BasicSocket` is the super class for all the `Socket` classes.

### Public Class Methods

do_not_reverse_lookup → true or false
Source

    static VALUE
    bsock_do_not_rev_lookup(VALUE _)
    {
        return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
    }

Gets the global `do_not_reverse_lookup` flag.

    BasicSocket.do_not_reverse_lookup  #=> false

do_not_reverse_lookup = bool
Source

    static VALUE
    bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
    {
        rsock_do_not_reverse_lookup = RTEST(val);
        return val;
    }

Sets the global `do_not_reverse_lookup` flag.

The flag is used for initial value of `do_not_reverse_lookup` for each socket.

    s1 = TCPSocket.new("localhost", 80)
    p s1.do_not_reverse_lookup                 #=> true
    BasicSocket.do_not_reverse_lookup = false
    s2 = TCPSocket.new("localhost", 80)
    p s2.do_not_reverse_lookup                 #=> false
    p s1.do_not_reverse_lookup                 #=> true

for_fd(fd) → basicsocket
Source

    static VALUE
    bsock_s_for_fd(VALUE klass, VALUE _descriptor)
    {
        rb_io_t *fptr;

        int descriptor = RB_NUM2INT(_descriptor);
        rsock_validate_descriptor(descriptor);

        VALUE sock = rsock_init_sock(rb_obj_alloc(klass), descriptor);

        GetOpenFile(sock, fptr);

        return sock;
    }

Returns a socket object which contains the file descriptor, fd.

    # If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
    STDIN_SOCK = Socket.for_fd(STDIN.fileno)
    p STDIN_SOCK.remote_address

### Public Instance Methods

close_read → nil
Source

    static VALUE
    bsock_close_read(VALUE sock)
    {
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        shutdown(fptr->fd, SHUT_RD);
        if (!(fptr->mode & FMODE_WRITABLE)) {
            return rb_io_close(sock);
        }
        fptr->mode &= ~FMODE_READABLE;

        return Qnil;
    }

Disallows further read using shutdown system call.

    s1, s2 = UNIXSocket.pair
    s1.close_read
    s2.puts #=> Broken pipe (Errno::EPIPE)

close_write → nil
Source

    static VALUE
    bsock_close_write(VALUE sock)
    {
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        if (!(fptr->mode & FMODE_READABLE)) {
            return rb_io_close(sock);
        }
        shutdown(fptr->fd, SHUT_WR);
        fptr->mode &= ~FMODE_WRITABLE;

        return Qnil;
    }

Disallows further write using shutdown system call.

    UNIXSocket.pair {|s1, s2|
      s1.print "ping"
      s1.close_write
      p s2.read        #=> "ping"
      s2.print "pong"
      s2.close
      p s1.read        #=> "pong"
    }

connect_address ()
Source

    # File ext/socket/lib/socket.rb, line 255
    def connect_address
      addr = local_address
      afamily = addr.afamily
      if afamily == Socket::AF_INET
        raise SocketError, "unbound IPv4 socket" if addr.ip_port == 0
        if addr.ip_address == "0.0.0.0"
          addr = Addrinfo.new(["AF_INET", addr.ip_port, nil, "127.0.0.1"], addr.pfamily, addr.socktype, addr.protocol)
        end
      elsif defined?(Socket::AF_INET6) && afamily == Socket::AF_INET6
        raise SocketError, "unbound IPv6 socket" if addr.ip_port == 0
        if addr.ip_address == "::"
          addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
        elsif addr.ip_address == "0.0.0.0" # MacOS X 10.4 returns "a.b.c.d" for IPv4-mapped IPv6 address.
          addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
        elsif addr.ip_address == "::ffff:0.0.0.0" # MacOS X 10.6 returns "::ffff:a.b.c.d" for IPv4-mapped IPv6 address.
          addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol)
        end
      elsif defined?(Socket::AF_UNIX) && afamily == Socket::AF_UNIX
        raise SocketError, "unbound Unix socket" if addr.unix_path == ""
      end
      addr
    end

Returns an address of the socket suitable for connect in the local machine.

This method returns self.local_address, except following condition.

- IPv4 unspecified address (0.0.0.0) is replaced by IPv4 loopback address (127.0.0.1).

- IPv6 unspecified address (::) is replaced by IPv6 loopback address (::1).

If the local address is not suitable for connect, `SocketError` is raised. IPv4 and IPv6 address which port is 0 is not suitable for connect. Unix domain socket which has no path is not suitable for connect.

    Addrinfo.tcp("0.0.0.0", 0).listen {|serv|
      p serv.connect_address #=> #<Addrinfo: 127.0.0.1:53660 TCP>
      serv.connect_address.connect {|c|
        s, _ = serv.accept
        p [c, s] #=> [#<Socket:fd 4>, #<Socket:fd 6>]
      }
    }

do_not_reverse_lookup → true or false
Source

    static VALUE
    bsock_do_not_reverse_lookup(VALUE sock)
    {
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
    }

Gets the `do_not_reverse_lookup` flag of basicsocket.

    require 'socket'

    BasicSocket.do_not_reverse_lookup = false
    TCPSocket.open("www.ruby-lang.org", 80) {|sock|
      p sock.do_not_reverse_lookup      #=> false
    }
    BasicSocket.do_not_reverse_lookup = true
    TCPSocket.open("www.ruby-lang.org", 80) {|sock|
      p sock.do_not_reverse_lookup      #=> true
    }

do_not_reverse_lookup = bool
Source

    static VALUE
    bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
    {
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        if (RTEST(state)) {
            fptr->mode |= FMODE_NOREVLOOKUP;
        }
        else {
            fptr->mode &= ~FMODE_NOREVLOOKUP;
        }
        return sock;
    }

Sets the `do_not_reverse_lookup` flag of basicsocket.

    TCPSocket.open("www.ruby-lang.org", 80) {|sock|
      p sock.do_not_reverse_lookup       #=> true
      p sock.peeraddr                    #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
      sock.do_not_reverse_lookup = false
      p sock.peeraddr                    #=> ["AF_INET", 80, "carbon.ruby-lang.org", "54.163.249.195"]
    }

getpeereid → [euid, egid]
Source

    static VALUE
    bsock_getpeereid(VALUE self)
    {
    #if defined(HAVE_GETPEEREID)
        rb_io_t *fptr;
        uid_t euid;
        gid_t egid;
        GetOpenFile(self, fptr);
        if (getpeereid(fptr->fd, &euid, &egid) == -1)
            rb_sys_fail("getpeereid(3)");
        return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
    #elif defined(SO_PEERCRED) /* GNU/Linux */
        rb_io_t *fptr;
        struct ucred cred;
        socklen_t len = sizeof(cred);
        GetOpenFile(self, fptr);
        if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
            rb_sys_fail("getsockopt(SO_PEERCRED)");
        return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
    #elif defined(HAVE_GETPEERUCRED) /* Solaris */
        rb_io_t *fptr;
        ucred_t *uc = NULL;
        VALUE ret;
        GetOpenFile(self, fptr);
        if (getpeerucred(fptr->fd, &uc) == -1)
            rb_sys_fail("getpeerucred(3C)");
        ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
        ucred_free(uc);
        return ret;
    #endif
    }

Returns the user and group on the peer of the UNIX socket. The result is a two element array which contains the effective uid and the effective gid.

    Socket.unix_server_loop("/tmp/sock") {|s|
      begin
        euid, egid = s.getpeereid

        # Check the connected client is myself or not.
        next if euid != Process.uid

        # do something about my resource.

      ensure
        s.close
      end
    }

getpeername → sockaddr
Source

    static VALUE
    bsock_getpeername(VALUE sock)
    {
        union_sockaddr buf;
        socklen_t len = (socklen_t)sizeof buf;
        socklen_t len0 = len;
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        if (getpeername(fptr->fd, &buf.addr, &len) < 0)
            rb_sys_fail("getpeername(2)");
        if (len0 < len) len = len0;
        return rb_str_new((char*)&buf, len);
    }

Returns the remote address of the socket as a sockaddr string.

    TCPServer.open("127.0.0.1", 1440) {|serv|
      c = TCPSocket.new("127.0.0.1", 1440)
      s = serv.accept
      p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
    }

If `Addrinfo` object is preferred over the binary string, use `BasicSocket#remote_address`.

getsockname → sockaddr
Source

    static VALUE
    bsock_getsockname(VALUE sock)
    {
        union_sockaddr buf;
        socklen_t len = (socklen_t)sizeof buf;
        socklen_t len0 = len;
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        if (getsockname(fptr->fd, &buf.addr, &len) < 0)
            rb_sys_fail("getsockname(2)");
        if (len0 < len) len = len0;
        return rb_str_new((char*)&buf, len);
    }

Returns the local address of the socket as a sockaddr string.

    TCPServer.open("127.0.0.1", 15120) {|serv|
      p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
    }

If `Addrinfo` object is preferred over the binary string, use `BasicSocket#local_address`.

getsockopt(level, optname) → socketoption
Source

    static VALUE
    bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
    {
        int level, option;
        socklen_t len;
        char *buf;
        rb_io_t *fptr;
        int family;

        GetOpenFile(sock, fptr);
        family = rsock_getfamily(fptr);
        level = rsock_level_arg(family, lev);
        option = rsock_optname_arg(family, level, optname);
        len = 256;
    #ifdef _AIX
        switch (option) {
          case SO_DEBUG:
          case SO_REUSEADDR:
          case SO_KEEPALIVE:
          case SO_DONTROUTE:
          case SO_BROADCAST:
          case SO_OOBINLINE:
            /* AIX doesn't set len for boolean options */
            len = sizeof(int);
        }
    #endif
        buf = ALLOCA_N(char,len);

        rb_io_check_closed(fptr);

        if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
            rsock_sys_fail_path("getsockopt(2)", fptr->pathv);

        return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
    }

Gets a socket option. These are protocol and system specific, see your local system documentation for details. The option is returned as a `Socket::Option` object.

### Parameters¶ ↑

- `level` is an integer, usually one of the SOL_ constants such as Socket::SOL_SOCKET, or a protocol level. A string or symbol of the name, possibly without prefix, is also accepted.

- `optname` is an integer, usually one of the SO_ constants, such as Socket::SO_REUSEADDR. A string or symbol of the name, possibly without prefix, is also accepted.

### Examples¶ ↑

Some socket options are integers with boolean values, in this case `getsockopt` could be called like this:

    reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool

    optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR)
    optval = optval.unpack "i"
    reuseaddr = optval[0] == 0 ? false : true

Some socket options are integers with numeric values, in this case `getsockopt` could be called like this:

    ipttl = sock.getsockopt(:IP, :TTL).int

    optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
    ipttl = optval.unpack1("i")

Option values may be structs. Decoding them can be complex as it involves examining your system headers to determine the correct definition. An example is a +struct linger+, which may be defined in your system headers as:

    struct linger {
      int l_onoff;
      int l_linger;
    };

In this case `getsockopt` could be called like this:

    # Socket::Option knows linger structure.
    onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger

    optval =  sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
    onoff, linger = optval.unpack "ii"
    onoff = onoff == 0 ? false : true

local_address → addrinfo
Source

    static VALUE
    bsock_local_address(VALUE sock)
    {
        union_sockaddr buf;
        socklen_t len = (socklen_t)sizeof buf;
        socklen_t len0 = len;
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        if (getsockname(fptr->fd, &buf.addr, &len) < 0)
            rb_sys_fail("getsockname(2)");
        if (len0 < len) len = len0;
        return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
    }

Returns an `Addrinfo` object for local address obtained by getsockname.

Note that addrinfo.protocol is filled by 0.

    TCPSocket.open("www.ruby-lang.org", 80) {|s|
      p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP>
    }

    TCPServer.open("127.0.0.1", 1512) {|serv|
      p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP>
    }

recv(maxlen[, flags[, outbuf]]) → mesg
Source

    static VALUE
    bsock_recv(int argc, VALUE *argv, VALUE sock)
    {
        return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
    }

Receives a message.

maxlen is the maximum number of bytes to receive.

flags should be a bitwise OR of Socket::MSG_* constants.

outbuf will contain only the received data after the method call even if it is not empty at the beginning.

    UNIXSocket.pair {|s1, s2|
      s1.puts "Hello World"
      p s2.recv(4)                     #=> "Hell"
      p s2.recv(4, Socket::MSG_PEEK)   #=> "o Wo"
      p s2.recv(4)                     #=> "o Wo"
      p s2.recv(10)                    #=> "rld\n"
    }

recv_nonblock(maxlen [, flags [, buf [, options ]]]) → mesg
Source

    # File ext/socket/lib/socket.rb, line 376
    def recv_nonblock(len, flag = 0, str = nil, exception: true)
      __recv_nonblock(len, flag, str, exception)
    end

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 result, mesg, is the data received.

When recvfrom(2) returns 0, `Socket#recv_nonblock` returns nil. In most cases it means the connection was closed, but for UDP connections it may mean an empty packet was received, as the underlying API makes it impossible to distinguish these two cases.

### Parameters¶ ↑

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

- `flags` - zero or more of the `MSG_` options

- `buf` - destination `String` buffer

- `options` - keyword hash, supporting ‘exception: false`

### Example¶ ↑

    serv = TCPServer.new("127.0.0.1", 0)
    af, port, host, addr = serv.addr
    c = TCPSocket.new(addr, port)
    s = serv.accept
    c.send "aaa", 0
    begin # emulate blocking recv.
      p s.recv_nonblock(10) #=> "aaa"
    rescue IO::WaitReadable
      IO.select([s])
      retry
    end

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

`BasicSocket#recv_nonblock` may raise any error corresponding to recvfrom(2) failure, including Errno::EWOULDBLOCK.

If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN, it is extended by `IO::WaitReadable`. So `IO::WaitReadable` can be used to rescue the exceptions for retrying recv_nonblock.

By specifying a keyword argument exception to `false`, you can indicate that `recv_nonblock` should not raise an `IO::WaitReadable` exception, but return the symbol `:wait_readable` instead.

### See¶ ↑

- `Socket#recvfrom`

recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) → [mesg, sender_addrinfo, rflags, *controls]
Source

    # File ext/socket/lib/socket.rb, line 431
    def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false)
      __recvmsg(dlen, flags, clen, scm_rights)
    end

recvmsg receives a message using recvmsg(2) system call in blocking manner.

maxmesglen is the maximum length of mesg to receive.

flags is bitwise OR of MSG_* constants such as Socket::MSG_PEEK.

maxcontrollen is the maximum length of controls (ancillary data) to receive.

opts is option hash. Currently :scm_rights=>bool is the only option.

:scm_rights option specifies that application expects SCM_RIGHTS control message. If the value is nil or false, application don’t expects SCM_RIGHTS control message. In this case, recvmsg closes the passed file descriptors immediately. This is the default behavior.

If :scm_rights value is neither nil nor false, application expects SCM_RIGHTS control message. In this case, recvmsg creates `IO` objects for each file descriptors for `Socket::AncillaryData#unix_rights` method.

The return value is 4-elements array.

mesg is a string of the received message.

sender_addrinfo is a sender socket address for connection-less socket. It is an `Addrinfo` object. For connection-oriented socket such as TCP, sender_addrinfo is platform dependent.

rflags is a flags on the received message which is bitwise OR of MSG_* constants such as Socket::MSG_TRUNC. It will be nil if the system uses 4.3BSD style old recvmsg system call.

controls is ancillary data which is an array of `Socket::AncillaryData` objects such as:

    #<Socket::AncillaryData: AF_UNIX SOCKET RIGHTS 7>

maxmesglen and maxcontrollen can be nil. In that case, the buffer will be grown until the message is not truncated. Internally, MSG_PEEK is used. Buffer full and MSG_CTRUNC are checked for truncation.

recvmsg can be used to implement recv_io as follows:

    mesg, sender_sockaddr, rflags, *controls = sock.recvmsg(:scm_rights=>true)
    controls.each {|ancdata|
      if ancdata.cmsg_is?(:SOCKET, :RIGHTS)
        return ancdata.unix_rights[0]
      end
    }

recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) → [data, sender_addrinfo, rflags, *controls]
Source

    # File ext/socket/lib/socket.rb, line 447
    def recvmsg_nonblock(dlen = nil, flags = 0, clen = nil,
                         scm_rights: false, exception: true)
      __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception)
    end

recvmsg receives a message using recvmsg(2) system call in non-blocking manner.

It is similar to `BasicSocket#recvmsg` but non-blocking flag is set before the system call and it doesn’t retry the system call.

By specifying a keyword argument exception to `false`, you can indicate that `recvmsg_nonblock` should not raise an `IO::WaitReadable` exception, but return the symbol `:wait_readable` instead.

remote_address → addrinfo
Source

    static VALUE
    bsock_remote_address(VALUE sock)
    {
        union_sockaddr buf;
        socklen_t len = (socklen_t)sizeof buf;
        socklen_t len0 = len;
        rb_io_t *fptr;

        GetOpenFile(sock, fptr);
        if (getpeername(fptr->fd, &buf.addr, &len) < 0)
            rb_sys_fail("getpeername(2)");
        if (len0 < len) len = len0;
        return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
    }

Returns an `Addrinfo` object for remote address obtained by getpeername.

Note that addrinfo.protocol is filled by 0.

    TCPSocket.open("www.ruby-lang.org", 80) {|s|
      p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP>
    }

    TCPServer.open("127.0.0.1", 1728) {|serv|
      c = TCPSocket.new("127.0.0.1", 1728)
      s = serv.accept
      p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP>
    }

send(mesg, flags [, dest_sockaddr]) → numbytes_sent
Source

    VALUE
    rsock_bsock_send(int argc, VALUE *argv, VALUE socket)
    {
        struct rsock_send_arg arg;
        VALUE flags, to;
        rb_io_t *fptr;
        rb_blocking_function_t *func;
        const char *funcname;

        rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);

        StringValue(arg.mesg);
        if (!NIL_P(to)) {
            SockAddrStringValue(to);
            to = rb_str_new4(to);
            arg.to = (struct sockaddr *)RSTRING_PTR(to);
            arg.tolen = RSTRING_SOCKLEN(to);
            func = rsock_sendto_blocking;
            funcname = "sendto(2)";
        }
        else {
            func = rsock_send_blocking;
            funcname = "send(2)";
        }

        RB_IO_POINTER(socket, fptr);

        arg.fd = fptr->fd;
        arg.flags = NUM2INT(flags);

        while (true) {
    #ifdef RSOCK_WAIT_BEFORE_BLOCKING
            rb_io_wait(socket, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil);
    #endif

            ssize_t n = (ssize_t)rb_io_blocking_region(fptr, func, &arg);

            if (n >= 0) return SSIZET2NUM(n);

            if (rb_io_maybe_wait_writable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) {
                continue;
            }

            rb_sys_fail(funcname);
        }
    }

send mesg via basicsocket.

mesg should be a string.

flags should be a bitwise OR of Socket::MSG_* constants.

dest_sockaddr should be a packed sockaddr string or an addrinfo.

    TCPSocket.open("localhost", 80) {|s|
      s.send "GET / HTTP/1.0\r\n\r\n", 0
      p s.read
    }

sendmsg(mesg, flags=0, dest_sockaddr=nil, *controls) → numbytes_sent
Source

    # File ext/socket/lib/socket.rb, line 307
    def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls)
      __sendmsg(mesg, flags, dest_sockaddr, controls)
    end

sendmsg sends a message using sendmsg(2) system call in blocking manner.

mesg is a string to send.

flags is bitwise OR of MSG_* constants such as Socket::MSG_OOB.

dest_sockaddr is a destination socket address for connection-less socket. It should be a sockaddr such as a result of `Socket.sockaddr_in`. An `Addrinfo` object can be used too.

controls is a list of ancillary data. The element of controls should be `Socket::AncillaryData` or 3-elements array. The 3-element array should contains cmsg_level, cmsg_type and data.

The return value, numbytes_sent is an integer which is the number of bytes sent.

sendmsg can be used to implement send_io as follows:

    # use Socket::AncillaryData.
    ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, io.fileno)
    sock.sendmsg("a", 0, nil, ancdata)

    # use 3-element array.
    ancdata = [:SOCKET, :RIGHTS, [io.fileno].pack("i!")]
    sock.sendmsg("\0", 0, nil, ancdata)

sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) → numbytes_sent
Source

    # File ext/socket/lib/socket.rb, line 323
    def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls,
                         exception: true)
      __sendmsg_nonblock(mesg, flags, dest_sockaddr, controls, exception)
    end

`sendmsg_nonblock` sends a message using sendmsg(2) system call in non-blocking manner.

It is similar to `BasicSocket#sendmsg` but the non-blocking flag is set before the system call and it doesn’t retry the system call.

By specifying a keyword argument exception to `false`, you can indicate that `sendmsg_nonblock` should not raise an `IO::WaitWritable` exception, but return the symbol `:wait_writable` instead.

setsockopt(level, optname, optval)
setsockopt(socketoption)
Source

    static VALUE
    bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
    {
        VALUE lev, optname, val;
        int family, level, option;
        rb_io_t *fptr;
        int i;
        char *v;
        int vlen;

        if (argc == 1) {
            lev = rb_funcall(argv[0], rb_intern("level"), 0);
            optname = rb_funcall(argv[0], rb_intern("optname"), 0);
            val = rb_funcall(argv[0], rb_intern("data"), 0);
        }
        else {
            rb_scan_args(argc, argv, "30", &lev, &optname, &val);
        }

        GetOpenFile(sock, fptr);
        family = rsock_getfamily(fptr);
        level = rsock_level_arg(family, lev);
        option = rsock_optname_arg(family, level, optname);

        switch (TYPE(val)) {
          case T_FIXNUM:
            i = FIX2INT(val);
            goto numval;
          case T_FALSE:
            i = 0;
            goto numval;
          case T_TRUE:
            i = 1;
          numval:
            v = (char*)&i; vlen = (int)sizeof(i);
            break;
          default:
            StringValue(val);
            v = RSTRING_PTR(val);
            vlen = RSTRING_SOCKLEN(val);
            break;
        }

        rb_io_check_closed(fptr);
        if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
            rsock_sys_fail_path("setsockopt(2)", fptr->pathv);

        return INT2FIX(0);
    }

Sets a socket option. These are protocol and system specific, see your local system documentation for details.

### Parameters¶ ↑

- `level` is an integer, usually one of the SOL_ constants such as Socket::SOL_SOCKET, or a protocol level. A string or symbol of the name, possibly without prefix, is also accepted.

- `optname` is an integer, usually one of the SO_ constants, such as Socket::SO_REUSEADDR. A string or symbol of the name, possibly without prefix, is also accepted.

- `optval` is the value of the option, it is passed to the underlying setsockopt() as a pointer to a certain number of bytes. How this is done depends on the type:

  - Integer: value is assigned to an int, and a pointer to the int is passed, with length of sizeof(int).

  - true or false: 1 or 0 (respectively) is assigned to an int, and the int is passed as for an `Integer`. Note that `false` must be passed, not `nil`.

  - String: the string’s data and length is passed to the socket.

- `socketoption` is an instance of `Socket::Option`

### Examples¶ ↑

Some socket options are integers with boolean values, in this case `setsockopt` could be called like this:

    sock.setsockopt(:SOCKET, :REUSEADDR, true)
    sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
    sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))

Some socket options are integers with numeric values, in this case `setsockopt` could be called like this:

    sock.setsockopt(:IP, :TTL, 255)
    sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
    sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))

Option values may be structs. Passing them can be complex as it involves examining your system headers to determine the correct definition. An example is an `ip_mreq`, which may be defined in your system headers as:

    struct ip_mreq {
      struct  in_addr imr_multiaddr;
      struct  in_addr imr_interface;
    };

In this case `setsockopt` could be called like this:

    optval = IPAddr.new("224.0.0.251").hton +
             IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton
    sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)

shutdown([how]) → 0
Source

    static VALUE
    bsock_shutdown(int argc, VALUE *argv, VALUE sock)
    {
        VALUE howto;
        int how;
        rb_io_t *fptr;

        rb_scan_args(argc, argv, "01", &howto);
        if (howto == Qnil)
            how = SHUT_RDWR;
        else {
            how = rsock_shutdown_how_arg(howto);
            if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
                rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
            }
        }
        GetOpenFile(sock, fptr);
        if (shutdown(fptr->fd, how) == -1)
            rb_sys_fail("shutdown(2)");

        return INT2FIX(0);
    }

Calls shutdown(2) system call.

s.shutdown(Socket::SHUT_RD) disallows further read.

s.shutdown(Socket::SHUT_WR) disallows further write.

s.shutdown(Socket::SHUT_RDWR) disallows further read and write.

how can be symbol or string:

- :RD, :SHUT_RD, “RD” and “SHUT_RD” are accepted as Socket::SHUT_RD.

- :WR, :SHUT_WR, “WR” and “SHUT_WR” are accepted as Socket::SHUT_WR.

- :RDWR, :SHUT_RDWR, “RDWR” and “SHUT_RDWR” are accepted as Socket::SHUT_RDWR.

  `UNIXSocket.pair` {|s1, s2|

      s1.puts "ping"
      s1.shutdown(:WR)
      p s2.read          #=> "ping\n"
      s2.puts "pong"
      s2.close
      p s1.read          #=> "pong\n"

  }