class TCPServer
TCPServer repräsentiert einen TCP/IP-Server-Socket.
Ein einfacher TCP-Server kann so aussehen:
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
Ein brauchbarerer Server (der mehrere Clients bedient)
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
Öffentliche Klassenmethoden
Source
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);
}
Erstellt einen neuen Server-Socket, der an port gebunden ist.
Wenn hostname angegeben ist, wird der Socket daran gebunden.
serv = TCPServer.new("127.0.0.1", 28561) s = serv.accept s.puts Time.now s.close
Intern ruft TCPServer.new die Funktion getaddrinfo() auf, um Adressen zu erhalten. Wenn getaddrinfo() mehrere Adressen zurückgibt, versucht TCPServer.new, für jede Adresse einen Server-Socket zu erstellen und gibt den ersten zurück, der erfolgreich war.
Öffentliche Instanzmethoden
Source
static VALUE
tcp_accept(VALUE server)
{
union_sockaddr buffer;
socklen_t length = sizeof(buffer);
return rsock_s_accept(rb_cTCPSocket, server, &buffer.addr, &length);
}
Akzeptiert eine eingehende Verbindung. Gibt ein neues TCPSocket-Objekt zurück.
TCPServer.open("127.0.0.1", 14641) {|serv| s = serv.accept s.puts Time.now s.close }
Source
# File ext/socket/lib/socket.rb, line 1777 def accept_nonblock(exception: true) __accept_nonblock(exception) end
Akzeptiert eine eingehende Verbindung mithilfe von accept(2), nachdem für den zugrunde liegenden Dateideskriptor O_NONBLOCK gesetzt wurde. Gibt einen akzeptierten TCPSocket für die eingehende Verbindung zurück.
Beispiel
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.
Siehe Socket#accept für die Ausnahmen, die ausgelöst werden können, wenn der Aufruf von TCPServer#accept_nonblock fehlschlägt.
TCPServer#accept_nonblock kann jede Ausnahme auslösen, die einem accept(2)-Fehler entspricht, einschließlich Errno::EWOULDBLOCK.
Wenn die Ausnahme Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO ist, wird sie von IO::WaitReadable erweitert. Daher kann IO::WaitReadable verwendet werden, um Ausnahmen zum erneuten Versuchen von accept_nonblock abzufangen.
Durch Angabe des Schlüsselwortarguments exception auf false können Sie angeben, dass accept_nonblock keine IO::WaitReadable-Ausnahme auslösen, sondern das Symbol :wait_readable zurückgeben soll.
Siehe
Source
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);
}
Wartet auf Verbindungen und verwendet die angegebene int als Backlog. Ein Aufruf von listen gilt nur, wenn der socket vom Typ SOCK_STREAM oder SOCK_SEQPACKET ist.
Parameter
-
backlog- die maximale Länge der Warteschlange für ausstehende Verbindungen.
Beispiel 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 )
Beispiel 2 (lauscht auf einem beliebigen Port, nur Unix-basierte Systeme)
require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) socket.listen( 1 )
Unix-basierte Ausnahmen
Auf Unix-basierten Systemen funktioniert dies, da eine neue sockaddr-Struktur für die Adresse ADDR_ANY für eine beliebige Portnummer erstellt wird, die vom Kernel zugewiesen wird. Unter Windows funktioniert dies nicht, da unter Windows der socket durch Aufruf von bind gebunden sein muss, bevor er listen kann.
Wenn die backlog-Menge die implementierungsabhängige maximale Warteschlangenlänge überschreitet, wird die maximale Warteschlangenlänge der Implementierung verwendet.
Auf Unix-basierten Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von listen fehlschlägt
-
Errno::EBADF - das socket-Argument ist kein gültiger Dateideskriptor
-
Errno::EDESTADDRREQ - der socket ist nicht an eine lokale Adresse gebunden, und das Protokoll unterstützt kein Lauschen auf einem ungebundenen Socket
-
Errno::EINVAL - der socket ist bereits verbunden
-
Errno::ENOTSOCK - das socket-Argument bezieht sich nicht auf einen Socket
-
Errno::EOPNOTSUPP - das socket-Protokoll unterstützt listen nicht
-
Errno::EACCES - der aufrufende Prozess hat keine geeigneten Berechtigungen
-
Errno::EINVAL - der socket wurde heruntergefahren
-
Errno::ENOBUFS - es stehen nicht genügend Systemressourcen zur Verfügung, um den Aufruf abzuschließen
Windows-Ausnahmen
Auf Windows-Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von listen fehlschlägt
-
Errno::ENETDOWN - das Netzwerk ist ausgefallen
-
Errno::EADDRINUSE - die lokale Adresse des Sockets ist bereits in Verwendung. Dies tritt normalerweise während der Ausführung von bind auf, kann aber verzögert werden, wenn der Aufruf von bind an eine teilweise Wildcard-Adresse (einschließlich ADDR_ANY) erfolgte und eine bestimmte Adresse zum Zeitpunkt des Aufrufs von listen zugewiesen werden muss.
-
Errno::EINPROGRESS - ein Windows Sockets 1.1-Aufruf ist in Bearbeitung oder der Dienstanbieter verarbeitet noch eine Callback-Funktion.
-
Errno::EINVAL - der
socketwurde nicht mit einem Aufruf von bind gebunden. -
Errno::EISCONN - der
socketist bereits verbunden -
Errno::EMFILE - keine Socket-Deskriptoren mehr verfügbar.
-
Errno::ENOBUFS - kein Pufferplatz verfügbar
-
Errno::ENOTSOC -
socketist kein Socket. -
Errno::EOPNOTSUPP - der referenzierte
socketist kein Typ, der die listen-Methode unterstützt.
Siehe
-
listen-Manpages auf Unix-basierten Systemen.
-
listen-Funktion in der Microsoft Winsock-Funktionsreferenz.
Source
static VALUE
tcp_sysaccept(VALUE server)
{
union_sockaddr buffer;
socklen_t length = sizeof(buffer);
return rsock_s_accept(0, server, &buffer.addr, &length);
}
Gibt einen Dateideskriptor einer akzeptierten Verbindung zurück.
TCPServer.open("127.0.0.1", 28561) {|serv| fd = serv.sysaccept s = IO.for_fd(fd) s.puts Time.now s.close }