Spec-Zone.ru › Ruby 4.0

класс TCPServer

Родительский класс:
TCPSocket

TCPServer представляет серверный сокет TCP/IP.

Простой TCP-сервер может выглядеть так:

require 'socket'

server = TCPServer.new 2000 # Server bind to port 2000
loop do
  client = server.accept    # Wait for a client to connect
  client.puts "Hello !"
  client.puts "Time is #{Time.now}"
  client.close
end

Более функциональный сервер (обслуживающий несколько клиентов):

require 'socket'

server = TCPServer.new 2000
loop do
  Thread.start(server.accept) do |client|
    client.puts "Hello !"
    client.puts "Time is #{Time.now}"
    client.close
  end
end

Публичные методы класса

new([hostname,] port) → tcpserver Показать исходный код
static VALUE
tcp_svr_init(int argc, VALUE *argv, VALUE sock)
{
    VALUE hostname, port;

    rb_scan_args(argc, argv, "011", &hostname, &port);
    return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER, Qnil, Qnil, Qnil, Qfalse, Qnil);
}

Создаёт новый серверный сокет, привязанный к port.

Если указан hostname, сокет привязывается к нему.

serv = TCPServer.new("127.0.0.1", 28561)
s = serv.accept
s.puts Time.now
s.close

Внутри TCPServer.new вызывает функцию getaddrinfo() для получения адресов. Если getaddrinfo() возвращает несколько адресов, TCPServer.new пытается создать серверный сокет для каждого адреса и возвращает первый успешно созданный.

Публичные методы экземпляра

accept → tcpsocket Показать исходный код
static VALUE
tcp_accept(VALUE server)
{
    union_sockaddr buffer;
    socklen_t length = sizeof(buffer);

    return rsock_s_accept(rb_cTCPSocket, server, &buffer.addr, &length);
}

Принимает входящее соединение. Возвращает новый объект TCPSocket.

TCPServer.open("127.0.0.1", 14641) {|serv|
  s = serv.accept
  s.puts Time.now
  s.close
}
accept_nonblock([options]) → tcpsocket Показать исходный код
# File ext/socket/lib/socket.rb, line 1777
def accept_nonblock(exception: true)
  __accept_nonblock(exception)
end

Принимает входящее соединение с помощью accept(2) после установки O_NONBLOCK для базового файлового дескриптора. Возвращает принятый TCPSocket для входящего соединения.

Пример

require 'socket'
serv = TCPServer.new(2202)
begin # emulate blocking accept
  sock = serv.accept_nonblock
rescue IO::WaitReadable, Errno::EINTR
  IO.select([serv])
  retry
end
# sock is an accepted socket.

Сведения об исключениях, которые могут быть вызваны при неудачном вызове TCPServer#accept_nonblock, см. в разделе Socket#accept.

TCPServer#accept_nonblock может вызвать любую ошибку, соответствующую сбою accept(2), включая Errno::EWOULDBLOCK.

Если исключение имеет тип Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED или Errno::EPROTO, к нему добавляется IO::WaitReadable. Поэтому для перехвата исключений и повторной попытки вызова accept_nonblock можно использовать IO::WaitReadable.

Указав ключевой аргумент exception для false, можно указать, что accept_nonblock не должен вызывать исключение IO::WaitReadable, а должен возвращать вместо него символ :wait_readable.

См. также

  • TCPServer#accept

  • Socket#accept

listen( int ) → 0 Показать исходный код
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 это не сработает, поскольку перед вызовом listen Windows требует привязать socket вызовом bind.

Если значение 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 от Microsoft

sysaccept → file_descriptor Показать исходный код
static VALUE
tcp_sysaccept(VALUE server)
{
    union_sockaddr buffer;
    socklen_t length = sizeof(buffer);

    return rsock_s_accept(0, server, &buffer.addr, &length);
}

Возвращает файловый дескриптор принятого соединения.

TCPServer.open("127.0.0.1", 28561) {|serv|
  fd = serv.sysaccept
  s = IO.for_fd(fd)
  s.puts Time.now
  s.close
}

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API