Class: UDPSocket

Inherits:
IPSocket show all
Defined in:
ext/socket/udpsocket.c,
ext/socket/udpsocket.c,
ext/socket/lib/socket.rb

Overview

UDPSocket represents a UDP/IP socket.

Instance Method Summary collapse

Methods inherited from IPSocket

#addr, getaddress, #inspect, #peeraddr, #recvfrom

Methods inherited from BasicSocket

#close_read, #close_write, #connect_address, do_not_reverse_lookup, #do_not_reverse_lookup, do_not_reverse_lookup=, #do_not_reverse_lookup=, for_fd, #getpeereid, #getpeername, #getsockname, #getsockopt, #local_address, #read_nonblock, #recv, #recv_nonblock, #recvmsg, #recvmsg_nonblock, #remote_address, #sendmsg, #sendmsg_nonblock, #setsockopt, #shutdown, #write_nonblock

Methods inherited from IO

#beep, #check_winsize_changed, #clear_screen, console, #console_mode, #console_mode=, #cooked, #cooked!, #cursor, #cursor=, #cursor_down, #cursor_left, #cursor_right, #cursor_up, default_console_size, #echo=, #echo?, #erase_line, #erase_screen, #expect, #getch, #getpass, #goto, #goto_column, #iflush, io_maybe_wait, io_maybe_wait_readable, io_maybe_wait_writable, io_wait, #ioflush, #noecho, #nonblock, #nonblock=, #nonblock?, #nread, #oflush, #pathconf, #pressed?, #raw, #raw!, #ready?, #scroll_backward, #scroll_forward, thread_fd_close, thread_fd_wait, thread_fd_writable, #wait, #wait_priority, #wait_readable, #wait_writable, #winsize, #winsize=

Constructor Details

#new([address_family]) ⇒ Object

Creates a new UDPSocket object.

address_family should be an integer, a string or a symbol: Socket::AF_INET, “AF_INET”, :INET, etc.

require 'socket'

UDPSocket.new                   #=> #<UDPSocket:fd 3>
UDPSocket.new(Socket::AF_INET6) #=> #<UDPSocket:fd 4>


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'ext/socket/udpsocket.c', line 28

static VALUE
udp_init(int argc, VALUE *argv, VALUE sock)
{
    VALUE arg;
    int family = AF_INET;
    int fd;

    if (rb_scan_args(argc, argv, "01", &arg) == 1) {
        family = rsock_family_arg(arg);
    }
    fd = rsock_socket(family, SOCK_DGRAM, 0);
    if (fd < 0) {
        rb_sys_fail("socket(2) - udp");
    }

    return rsock_init_sock(sock, fd);
}

Instance Method Details

#bind(host, port) ⇒ Object

Binds udpsocket to host:port.

u1 = UDPSocket.new
u1.bind("127.0.0.1", 4913)
u1.send "message-to-self", 0, "127.0.0.1", 4913
p u1.recvfrom(10) #=> ["message-to", ["AF_INET", 4913, "localhost", "127.0.0.1"]]


131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'ext/socket/udpsocket.c', line 131

static VALUE
udp_bind(VALUE sock, VALUE host, VALUE port)
{
    struct udp_arg arg;
    VALUE ret;

    GetOpenFile(sock, arg.fptr);
    arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
    ret = rb_ensure(udp_bind_internal, (VALUE)&arg,
                    rsock_freeaddrinfo, (VALUE)arg.res);
    if (!ret) rsock_sys_fail_host_port("bind(2)", host, port);
    return INT2FIX(0);
}

#connect(host, port) ⇒ 0

Connects udpsocket to host:port.

This makes possible to send without destination address.

u1 = UDPSocket.new
u1.bind("127.0.0.1", 4913)
u2 = UDPSocket.new
u2.connect("127.0.0.1", 4913)
u2.send "uuuu", 0
p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]]

Returns:

  • (0)


86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'ext/socket/udpsocket.c', line 86

static VALUE
udp_connect(VALUE sock, VALUE host, VALUE port)
{
    struct udp_arg arg;
    VALUE ret;

    GetOpenFile(sock, arg.fptr);
    arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
    ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
                    rsock_freeaddrinfo, (VALUE)arg.res);
    if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
    return INT2FIX(0);
}

#recvfrom_nonblock(len, flag = 0, outbuf = nil, exception: true) ⇒ Object

call-seq:

udpsocket.recvfrom_nonblock(maxlen [, flags[, outbuf [, options]]]) => [mesg, sender_inet_addr]

Receives up to maxlen bytes from udpsocket 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_inet_addr, is an array to represent the sender address.

When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. In most cases it means the connection was closed, but it may also 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

  • outbuf - destination String buffer

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

Example

require ‘socket’ s1 = UDPSocket.new s1.bind(“127.0.0.1”, 0) s2 = UDPSocket.new s2.bind(“127.0.0.1”, 0) s2.connect(*s1.addr.values_at(3,1)) s1.connect(*s2.addr.values_at(3,1)) s1.send “aaa”, 0 begin # emulate blocking recvfrom p s2.recvfrom_nonblock(10) #=> [“aaa”, [“AF_INET”, 33302, “localhost.localdomain”, “127.0.0.1”]] rescue IO::WaitReadable IO.select() retry end

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

UDPSocket#recvfrom_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 recvfrom_nonblock.

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

See

  • Socket#recvfrom



1277
1278
1279
# File 'ext/socket/lib/socket.rb', line 1277

def recvfrom_nonblock(len, flag = 0, outbuf = nil, exception: true)
  __recvfrom_nonblock(len, flag, outbuf, exception)
end

#send(mesg, flags, host, port) ⇒ Object #send(mesg, flags, sockaddr_to) ⇒ Object #send(mesg, flags) ⇒ Object

Sends mesg via udpsocket.

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

u1 = UDPSocket.new
u1.bind("127.0.0.1", 4913)

u2 = UDPSocket.new
u2.send "hi", 0, "127.0.0.1", 4913

mesg, addr = u1.recvfrom(10)
u1.send mesg, 0, addr[3], addr[1]

p u2.recv(100) #=> "hi"


202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'ext/socket/udpsocket.c', line 202

static VALUE
udp_send(int argc, VALUE *argv, VALUE sock)
{
    VALUE flags, host, port;
    struct udp_send_arg arg;
    VALUE ret;

    if (argc == 2 || argc == 3) {
        return rsock_bsock_send(argc, argv, sock);
    }
    rb_scan_args(argc, argv, "4", &arg.sarg.mesg, &flags, &host, &port);

    StringValue(arg.sarg.mesg);
    GetOpenFile(sock, arg.fptr);
    arg.sarg.fd = arg.fptr->fd;
    arg.sarg.flags = NUM2INT(flags);
    arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
    ret = rb_ensure(udp_send_internal, (VALUE)&arg,
                    rsock_freeaddrinfo, (VALUE)arg.res);
    if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port);
    return ret;
}