In Files

  • socket/socket.c

UDPSocket

Public Class Methods

new(p1 = v1) click to toggle source
 
               static VALUE
udp_init(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    VALUE arg;
    int socktype = AF_INET;
    int fd;

    rb_secure(3);
    if (rb_scan_args(argc, argv, "01", &arg) == 1) {
        socktype = NUM2INT(arg);
    }
    fd = ruby_socket(socktype, SOCK_DGRAM, 0);
    if (fd < 0) {
        rb_sys_fail("socket(2) - udp");
    }

    return init_sock(sock, fd);
}
            

Public Instance Methods

bind(p1, p2) click to toggle source
 
               static VALUE
udp_bind(sock, host, port)
    VALUE sock, host, port;
{
    rb_io_t *fptr;
    struct addrinfo *res0, *res;

    rb_secure(3);
    res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
    GetOpenFile(sock, fptr);
    for (res = res0; res; res = res->ai_next) {
        if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
            continue;
        }
        freeaddrinfo(res0);
        return INT2FIX(0);
    }
    freeaddrinfo(res0);
    rb_sys_fail("bind(2)");
    return INT2FIX(0);
}
            
connect(p1, p2) click to toggle source
 
               static VALUE
udp_connect(sock, host, port)
    VALUE sock, host, port;
{
    rb_io_t *fptr;
    struct udp_arg arg;
    VALUE ret;

    rb_secure(3);
    arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0);
    GetOpenFile(sock, fptr);
    arg.fd = fileno(fptr->f);
    ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
                    RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res);
    if (!ret) rb_sys_fail("connect(2)");
    return INT2FIX(0);
}
            
recvfrom_nonblock(maxlen) => [mesg, sender_inet_addr] click to toggle source
recvfrom_nonblock(maxlen, flags) => [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#recvfrom_nonblock returns an empty string as data. It means an empty packet.

Parameters

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

  • flags - zero or more of the MSG_ options

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
IO.select([s2])
p s2.recvfrom_nonblock(10)  #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]

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

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

See

 
               static VALUE
udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
{
    return s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
}
            
send(p1, p2, p3, p4) click to toggle source
 
               static VALUE
udp_send(argc, argv, sock)
    int argc;
    VALUE *argv;
    VALUE sock;
{
    VALUE mesg, flags, host, port;
    rb_io_t *fptr;
    FILE *f;
    int n;
    struct addrinfo *res0, *res;

    if (argc == 2 || argc == 3) {
        return bsock_send(argc, argv, sock);
    }
    rb_secure(4);
    rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);

    StringValue(mesg);
    res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
    GetOpenFile(sock, fptr);
    f = GetWriteFile(fptr);
    for (res = res0; res; res = res->ai_next) {
      retry:
        n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags),
                   res->ai_addr, res->ai_addrlen);
        if (n >= 0) {
            freeaddrinfo(res0);
            return INT2FIX(n);
        }
        if (rb_io_wait_writable(fileno(f))) {
            goto retry;
        }
    }
    freeaddrinfo(res0);
    rb_sys_fail("sendto(2)");
    return INT2FIX(n);
}