класс UNIXServer
UNIXServer представляет сокет сервера потокового соединения доменной области UNIX.
Публичные методы класса
static VALUE
unix_svr_init(VALUE sock, VALUE path)
{
return rsock_init_unixsock(sock, path, 1);
} Создаёт новый сокет сервера UNIX, привязанный к path.
require 'socket'
serv = UNIXServer.new("/tmp/sock")
s = serv.accept
p s.read
Публичные методы экземпляра
static VALUE
unix_accept(VALUE sock)
{
rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(struct sockaddr_un);
return rsock_s_accept(rb_cUNIXSocket, fptr->fd,
(struct sockaddr*)&from, &fromlen);
} Принимает входящее соединение. Возвращает новый объект UNIXSocket.
UNIXServer.open("/tmp/sock") {|serv|
UNIXSocket.open("/tmp/sock") {|c|
s = serv.accept
s.puts "hi"
s.close
p c.read #=> "hi\n"
}
}
# File ext/socket/lib/socket.rb, line 1352 def accept_nonblock(exception: true) __accept_nonblock(exception) end
Принимает входящее соединение с использованием accept(2) после установки O_NONBLOCK для базового дескриптора файла. Возвращает принятый UNIXSocket для входящего соединения.
Пример
require 'socket'
serv = UNIXServer.new("/tmp/sock")
begin # emulate blocking accept
sock = serv.accept_nonblock
rescue IO::WaitReadable, Errno::EINTR
IO.select([serv])
retry
end
# sock is an accepted socket.
Обратитесь к Socket#accept для получения информации об исключениях, которые могут быть выброшены, если вызов #accept_nonblock завершился неудачно.
#accept_nonblock может вызывать любое исключение, соответствующее ошибке accept(2), включая Errno::EWOULDBLOCK.
Если исключение является Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED или Errno::EPROTO, оно дополняется IO::WaitReadable. Поэтому IO::WaitReadable можно использовать для перехвата исключений и повторной попытки #accept_nonblock.
Указав ключевое слово exception в false, вы можете указать, что #accept_nonblock не должен генерировать исключение IO::WaitReadable, а вместо этого вернуть символ :wait_readable.
См. также
VALUE
rsock_sock_listen(VALUE sock, VALUE log)
{
rb_io_t *fptr;
int backlog;
backlog = NUM2INT(log);
GetOpenFile(sock, fptr);
if (listen(fptr->fd, backlog) < 0)
rb_sys_fail("listen(2)");
return INT2FIX(0);
} Прослушивает соединения с указанным int в качестве размера очереди. Вызов listen применяется только если тип socket - SOCK_STREAM или SOCK_SEQPACKET.
Параметр
-
backlog- максимальная длина очереди ожидающих соединений.
Пример 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 )
Пример 2 (прослушивание на произвольном порту, только для систем на базе UNIX):
require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) socket.listen( 1 )
Исключения для систем на базе UNIX
На системах на базе UNIX это сработает, потому что создается новая структура sockaddr по адресу ADDR_ANY, для произвольного номера порта, переданного ядром. Это не сработает в Windows, так как Windows требует, чтобы socket была привязана с помощью bind, прежде чем можно будет использовать listen.
Если размер backlog превышает максимальную длину очереди, зависящую от реализации, будет использована максимальная длина очереди реализации.
На системах на базе UNIX при неудачном вызове listen могут быть выброшены следующие системные исключения:
-
Errno::EBADF - аргумент socket не является допустимым дескриптором файла
-
Errno::EDESTADDRREQ - socket не привязан к локальному адресу, и протокол не поддерживает прослушивание на непривязанном сокете
-
Errno::EINVAL - socket уже подключен
-
Errno::ENOTSOCK - аргумент socket не ссылается на сокет
-
Errno::EOPNOTSUPP - протокол socket не поддерживает listen
-
Errno::EACCES - у вызывающего процесса нет соответствующих привилегий
-
Errno::EINVAL - socket был закрыт
-
Errno::ENOBUFS - в системе недостаточно ресурсов для завершения вызова
Исключения для Windows
На системах Windows при неудачном вызове listen могут быть выброшены следующие системные исключения:
-
Errno::ENETDOWN - сеть отключена
-
Errno::EADDRINUSE - локальный адрес сокета уже используется. Это обычно происходит во время выполнения bind, но может быть отложено, если вызов bind был к частичному универсальному адресу (включающему ADDR_ANY), и если конкретный адрес необходимо зафиксировать в момент вызова listen
-
Errno::EINPROGRESS - выполняется вызов Windows Sockets 1.1 или поставщик сервиса все еще обрабатывает функцию обратного вызова
-
Errno::EINVAL -
socketне был привязан с помощью вызова bind. -
Errno::EISCONN -
socketуже подключен -
Errno::EMFILE - больше нет доступных дескрипторов сокетов
-
Errno::ENOBUFS - нет доступного буферного пространства
-
Errno::ENOTSOC -
socketне является сокетом -
Errno::EOPNOTSUPP - ссылка
socketне является типом, поддерживающим метод listen
См. также
-
Справочные страницы listen на системах на базе UNIX
-
Функция listen в справочнике по функциям Winsock Майкрософт
static VALUE
unix_sysaccept(VALUE sock)
{
rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(struct sockaddr_un);
return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen);
} Принимает новое соединение. Возвращает новый дескриптор файла, который представляет собой целое число.
UNIXServer.open("/tmp/sock") {|serv|
UNIXSocket.open("/tmp/sock") {|c|
fd = serv.sysaccept
s = IO.new(fd)
s.puts "hi"
s.close
p c.read #=> "hi\n"
}
}
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.