класс UDPSocket
UDPSocket представляет сокет UDP/IP.
Публичные методы класса
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);
} Создаёт новый объект UDPSocket.
address_family должно быть целым числом, строкой или символом: Socket::AF_INET, “AF_INET”, :INET и т. д.
require 'socket' UDPSocket.new #=> #<UDPSocket:fd 3> UDPSocket.new(Socket::AF_INET6) #=> #<UDPSocket:fd 4>
Публичные методы экземпляра
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);
} Связывает udpsocket с 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"]]
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);
} Подключает udpsocket к host:port.
Это позволяет отправлять данные без указания адреса получателя.
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"]]
# 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
Принимает до maxlen байт данных от udpsocket с использованием recvfrom(2) после установки O_NONBLOCK для базового дескриптора файла. flags равно нулю или большему числу MSG_ опций. Первый элемент результата, mesg, — это полученные данные. Второй элемент, sender_inet_addr, — массив для представления адреса отправителя.
Когда recvfrom(2) возвращает 0, Socket#recv_nonblock возвращает nil. В большинстве случаев это означает закрытие соединения, но также может означать получение пустого пакета, поскольку базовый API не позволяет различать эти два случая.
Параметры
-
maxlen— количество байтов для получения из сокета -
flags— ноль или болееMSG_опций -
outbuf— буфер назначенияString -
options— хеш-словарь, поддерживающий ‘exception: false`
Пример
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([s2])
retry
end
Обратитесь к Socket#recvfrom для получения информации об исключениях, которые могут быть выброшены при неудачном вызове recvfrom_nonblock.
UDPSocket#recvfrom_nonblock может вызвать любое исключение, соответствующее ошибке recvfrom(2), включая Errno::EWOULDBLOCK.
Если исключение равно Errno::EWOULDBLOCK или Errno::EAGAIN, оно дополняется IO::WaitReadable. Таким образом, IO::WaitReadable можно использовать для обработки исключений с целью повторной попытки recvfrom_nonblock.
Указав ключевой аргумент exception в false, можно указать, что recvfrom_nonblock не должен вызывать исключение IO::WaitReadable, а должен возвращать символ :wait_readable вместо этого.
См. также
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;
} Отправляет mesg через udpsocket.
flags должен быть побитовым ИЛИ констант Socket::MSG_*.
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"
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.