класс 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 1337 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 не поддерживает прослушивание
-
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 Microsoft
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.