class BasicSocket
BasicSocket ist die Oberklasse für alle Socket-Klassen.
Öffentliche Klassenmethoden
Source
static VALUE
bsock_do_not_rev_lookup(VALUE _)
{
return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
}
Ruft das globale Flag do_not_reverse_lookup ab.
BasicSocket.do_not_reverse_lookup #=> false
Source
static VALUE
bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
{
rsock_do_not_reverse_lookup = RTEST(val);
return val;
}
Setzt das globale Flag do_not_reverse_lookup.
Das Flag wird für den anfänglichen Wert von do_not_reverse_lookup für jeden Socket verwendet.
s1 = TCPSocket.new("localhost", 80) p s1.do_not_reverse_lookup #=> true BasicSocket.do_not_reverse_lookup = false s2 = TCPSocket.new("localhost", 80) p s2.do_not_reverse_lookup #=> false p s1.do_not_reverse_lookup #=> true
Source
static VALUE
bsock_s_for_fd(VALUE klass, VALUE _descriptor)
{
rb_io_t *fptr;
int descriptor = RB_NUM2INT(_descriptor);
rsock_validate_descriptor(descriptor);
VALUE sock = rsock_init_sock(rb_obj_alloc(klass), descriptor);
GetOpenFile(sock, fptr);
return sock;
}
Gibt ein Socket-Objekt zurück, das den Dateideskriptor fd enthält.
# If invoked by inetd, STDIN/STDOUT/STDERR is a socket. STDIN_SOCK = Socket.for_fd(STDIN.fileno) p STDIN_SOCK.remote_address
Öffentliche Instanzmethoden
Source
static VALUE
bsock_close_read(VALUE sock)
{
rb_io_t *fptr;
GetOpenFile(sock, fptr);
shutdown(fptr->fd, SHUT_RD);
if (!(fptr->mode & FMODE_WRITABLE)) {
return rb_io_close(sock);
}
fptr->mode &= ~FMODE_READABLE;
return Qnil;
}
Verhindert weitere Lesevorgänge über den shutdown-Systemaufruf.
s1, s2 = UNIXSocket.pair s1.close_read s2.puts #=> Broken pipe (Errno::EPIPE)
Source
static VALUE
bsock_close_write(VALUE sock)
{
rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (!(fptr->mode & FMODE_READABLE)) {
return rb_io_close(sock);
}
shutdown(fptr->fd, SHUT_WR);
fptr->mode &= ~FMODE_WRITABLE;
return Qnil;
}
Verhindert weitere Schreibvorgänge über den shutdown-Systemaufruf.
UNIXSocket.pair {|s1, s2| s1.print "ping" s1.close_write p s2.read #=> "ping" s2.print "pong" s2.close p s1.read #=> "pong" }
Source
# File ext/socket/lib/socket.rb, line 255 def connect_address addr = local_address afamily = addr.afamily if afamily == Socket::AF_INET raise SocketError, "unbound IPv4 socket" if addr.ip_port == 0 if addr.ip_address == "0.0.0.0" addr = Addrinfo.new(["AF_INET", addr.ip_port, nil, "127.0.0.1"], addr.pfamily, addr.socktype, addr.protocol) end elsif defined?(Socket::AF_INET6) && afamily == Socket::AF_INET6 raise SocketError, "unbound IPv6 socket" if addr.ip_port == 0 if addr.ip_address == "::" addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol) elsif addr.ip_address == "0.0.0.0" # MacOS X 10.4 returns "a.b.c.d" for IPv4-mapped IPv6 address. addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol) elsif addr.ip_address == "::ffff:0.0.0.0" # MacOS X 10.6 returns "::ffff:a.b.c.d" for IPv4-mapped IPv6 address. addr = Addrinfo.new(["AF_INET6", addr.ip_port, nil, "::1"], addr.pfamily, addr.socktype, addr.protocol) end elsif defined?(Socket::AF_UNIX) && afamily == Socket::AF_UNIX raise SocketError, "unbound Unix socket" if addr.unix_path == "" end addr end
Gibt eine Adresse des Sockets zurück, die für die Verbindung auf dem lokalen Rechner geeignet ist.
Diese Methode gibt self.local_address zurück, mit folgenden Ausnahmen.
-
IPv4-unspezifizierte Adresse (0.0.0.0) wird durch IPv4-Loopback-Adresse (127.0.0.1) ersetzt.
-
IPv6-unspezifizierte Adresse (::) wird durch IPv6-Loopback-Adresse (::1) ersetzt.
Wenn die lokale Adresse nicht für eine Verbindung geeignet ist, wird SocketError ausgelöst. IPv4- und IPv6-Adressen mit Port 0 sind nicht für Verbindungen geeignet. Unix-Domain-Sockets ohne Pfad sind nicht für Verbindungen geeignet.
Addrinfo.tcp("0.0.0.0", 0).listen {|serv| p serv.connect_address #=> #<Addrinfo: 127.0.0.1:53660 TCP> serv.connect_address.connect {|c| s, _ = serv.accept p [c, s] #=> [#<Socket:fd 4>, #<Socket:fd 6>] } }
Source
static VALUE
bsock_do_not_reverse_lookup(VALUE sock)
{
rb_io_t *fptr;
GetOpenFile(sock, fptr);
return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
}
Ruft das Flag do_not_reverse_lookup des basicsocket ab.
require 'socket' BasicSocket.do_not_reverse_lookup = false TCPSocket.open("www.ruby-lang.org", 80) {|sock| p sock.do_not_reverse_lookup #=> false } BasicSocket.do_not_reverse_lookup = true TCPSocket.open("www.ruby-lang.org", 80) {|sock| p sock.do_not_reverse_lookup #=> true }
Source
static VALUE
bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
{
rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (RTEST(state)) {
fptr->mode |= FMODE_NOREVLOOKUP;
}
else {
fptr->mode &= ~FMODE_NOREVLOOKUP;
}
return sock;
}
Setzt das Flag do_not_reverse_lookup des basicsocket.
TCPSocket.open("www.ruby-lang.org", 80) {|sock| p sock.do_not_reverse_lookup #=> true p sock.peeraddr #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"] sock.do_not_reverse_lookup = false p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "54.163.249.195"] }
Source
static VALUE
bsock_getpeereid(VALUE self)
{
#if defined(HAVE_GETPEEREID)
rb_io_t *fptr;
uid_t euid;
gid_t egid;
GetOpenFile(self, fptr);
if (getpeereid(fptr->fd, &euid, &egid) == -1)
rb_sys_fail("getpeereid(3)");
return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
#elif defined(SO_PEERCRED) /* GNU/Linux */
rb_io_t *fptr;
struct ucred cred;
socklen_t len = sizeof(cred);
GetOpenFile(self, fptr);
if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
rb_sys_fail("getsockopt(SO_PEERCRED)");
return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
#elif defined(HAVE_GETPEERUCRED) /* Solaris */
rb_io_t *fptr;
ucred_t *uc = NULL;
VALUE ret;
GetOpenFile(self, fptr);
if (getpeerucred(fptr->fd, &uc) == -1)
rb_sys_fail("getpeerucred(3C)");
ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
ucred_free(uc);
return ret;
#endif
}
Gibt den Benutzer und die Gruppe des Peers des UNIX-Sockets zurück. Das Ergebnis ist ein zweielementiges Array, das die effektive UID und die effektive GID enthält.
Socket.unix_server_loop("/tmp/sock") {|s| begin euid, egid = s.getpeereid # Check the connected client is myself or not. next if euid != Process.uid # do something about my resource. ensure s.close end }
Source
static VALUE
bsock_getpeername(VALUE sock)
{
union_sockaddr buf;
socklen_t len = (socklen_t)sizeof buf;
socklen_t len0 = len;
rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getpeername(fptr->fd, &buf.addr, &len) < 0)
rb_sys_fail("getpeername(2)");
if (len0 < len) len = len0;
return rb_str_new((char*)&buf, len);
}
Gibt die Remote-Adresse des Sockets als sockaddr-String zurück.
TCPServer.open("127.0.0.1", 1440) {|serv| c = TCPSocket.new("127.0.0.1", 1440) s = serv.accept p s.getpeername #=> "\x02\x00\x82u\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" }
Wenn ein Addrinfo-Objekt einem Binärstring vorgezogen wird, verwenden Sie BasicSocket#remote_address.
Source
static VALUE
bsock_getsockname(VALUE sock)
{
union_sockaddr buf;
socklen_t len = (socklen_t)sizeof buf;
socklen_t len0 = len;
rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getsockname(fptr->fd, &buf.addr, &len) < 0)
rb_sys_fail("getsockname(2)");
if (len0 < len) len = len0;
return rb_str_new((char*)&buf, len);
}
Gibt die lokale Adresse des Sockets als sockaddr-String zurück.
TCPServer.open("127.0.0.1", 15120) {|serv| p serv.getsockname #=> "\x02\x00;\x10\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" }
Wenn ein Addrinfo-Objekt einem Binärstring vorgezogen wird, verwenden Sie BasicSocket#local_address.
Source
static VALUE
bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
{
int level, option;
socklen_t len;
char *buf;
rb_io_t *fptr;
int family;
GetOpenFile(sock, fptr);
family = rsock_getfamily(fptr);
level = rsock_level_arg(family, lev);
option = rsock_optname_arg(family, level, optname);
len = 256;
#ifdef _AIX
switch (option) {
case SO_DEBUG:
case SO_REUSEADDR:
case SO_KEEPALIVE:
case SO_DONTROUTE:
case SO_BROADCAST:
case SO_OOBINLINE:
/* AIX doesn't set len for boolean options */
len = sizeof(int);
}
#endif
buf = ALLOCA_N(char,len);
rb_io_check_closed(fptr);
if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
rsock_sys_fail_path("getsockopt(2)", fptr->pathv);
return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
}
Ruft eine Socket-Option ab. Diese sind protokoll- und systemspezifisch. Informationen finden Sie in der Dokumentation Ihres lokalen Systems. Die Option wird als Socket::Option-Objekt zurückgegeben.
Parameter
-
levelist eine Ganzzahl, normalerweise eine der SOL_-Konstanten wie Socket::SOL_SOCKET oder eine Protokollebene. Ein String oder Symbol des Namens, möglicherweise ohne Präfix, wird ebenfalls akzeptiert. -
optnameist eine Ganzzahl, normalerweise eine der SO_-Konstanten wie Socket::SO_REUSEADDR. Ein String oder Symbol des Namens, möglicherweise ohne Präfix, wird ebenfalls akzeptiert.
Beispiele
Einige Socket-Optionen sind Ganzzahlen mit booleschen Werten. In diesem Fall kann getsockopt wie folgt aufgerufen werden
reuseaddr = sock.getsockopt(:SOCKET, :REUSEADDR).bool optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR) optval = optval.unpack "i" reuseaddr = optval[0] == 0 ? false : true
Einige Socket-Optionen sind Ganzzahlen mit numerischen Werten. In diesem Fall kann getsockopt wie folgt aufgerufen werden
ipttl = sock.getsockopt(:IP, :TTL).int optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL) ipttl = optval.unpack1("i")
Optionswerte können Strukturen sein. Deren Dekodierung kann komplex sein, da sie die Untersuchung Ihrer System-Header erfordert, um die korrekte Definition zu ermitteln. Ein Beispiel ist eine +struct linger+, die in Ihren System-Headern wie folgt definiert sein kann:
struct linger { int l_onoff; int l_linger; };
In diesem Fall kann getsockopt wie folgt aufgerufen werden
# Socket::Option knows linger structure. onoff, linger = sock.getsockopt(:SOCKET, :LINGER).linger optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER) onoff, linger = optval.unpack "ii" onoff = onoff == 0 ? false : true
Source
static VALUE
bsock_local_address(VALUE sock)
{
union_sockaddr buf;
socklen_t len = (socklen_t)sizeof buf;
socklen_t len0 = len;
rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getsockname(fptr->fd, &buf.addr, &len) < 0)
rb_sys_fail("getsockname(2)");
if (len0 < len) len = len0;
return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
}
Gibt ein Addrinfo-Objekt für die lokale Adresse zurück, die mit getsockname abgerufen wurde.
Beachten Sie, dass addrinfo.protocol mit 0 gefüllt ist.
TCPSocket.open("www.ruby-lang.org", 80) {|s| p s.local_address #=> #<Addrinfo: 192.168.0.129:36873 TCP> } TCPServer.open("127.0.0.1", 1512) {|serv| p serv.local_address #=> #<Addrinfo: 127.0.0.1:1512 TCP> }
Source
static VALUE
bsock_recv(int argc, VALUE *argv, VALUE sock)
{
return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
}
Empfängt eine Nachricht.
maxlen ist die maximale Anzahl der zu empfangenden Bytes.
flags sollte eine bitweise OR-Verknüpfung der Socket::MSG_* Konstanten sein.
outbuf enthält nach dem Methodenaufruf nur die empfangenen Daten, auch wenn es am Anfang nicht leer ist.
UNIXSocket.pair {|s1, s2| s1.puts "Hello World" p s2.recv(4) #=> "Hell" p s2.recv(4, Socket::MSG_PEEK) #=> "o Wo" p s2.recv(4) #=> "o Wo" p s2.recv(10) #=> "rld\n" }
Source
# File ext/socket/lib/socket.rb, line 376 def recv_nonblock(len, flag = 0, str = nil, exception: true) __recv_nonblock(len, flag, str, exception) end
Empfängt bis zu maxlen Bytes vom socket mit recvfrom(2), nachdem für den zugrundeliegenden Dateideskriptor O_NONBLOCK gesetzt wurde. flags ist Null oder mehr der MSG_-Optionen. Das Ergebnis, mesg, sind die empfangenen Daten.
Wenn recvfrom(2) 0 zurückgibt, gibt Socket#recv_nonblock nil zurück. In den meisten Fällen bedeutet dies, dass die Verbindung geschlossen wurde, aber bei UDP-Verbindungen kann dies bedeuten, dass ein leeres Paket empfangen wurde, da die zugrundeliegende API es unmöglich macht, diese beiden Fälle zu unterscheiden.
Parameter
-
maxlen- die Anzahl der Bytes, die vom Socket empfangen werden sollen -
flags- null oder mehr derMSG_-Optionen. -
buf- Ziel-String-Puffer -
options- Keyword-Hash, unterstützt 'exception: false`
Beispiel
serv = TCPServer.new("127.0.0.1", 0) af, port, host, addr = serv.addr c = TCPSocket.new(addr, port) s = serv.accept c.send "aaa", 0 begin # emulate blocking recv. p s.recv_nonblock(10) #=> "aaa" rescue IO::WaitReadable IO.select([s]) retry end
Beziehen Sie sich auf Socket#recvfrom für die Ausnahmen, die ausgelöst werden können, wenn der Aufruf von recv_nonblock fehlschlägt.
BasicSocket#recv_nonblock kann jede Ausnahme auslösen, die einem recvfrom(2)-Fehler entspricht, einschließlich Errno::EWOULDBLOCK.
Wenn die Ausnahme Errno::EWOULDBLOCK oder Errno::EAGAIN ist, wird sie von IO::WaitReadable erweitert. Daher kann IO::WaitReadable zum Abfangen der Ausnahmen für das Wiederholen von recv_nonblock verwendet werden.
Durch die Angabe eines Keyword-Arguments exception auf false können Sie angeben, dass recv_nonblock keine IO::WaitReadable-Ausnahme auslösen, sondern das Symbol :wait_readable zurückgeben soll.
Siehe
Source
# File ext/socket/lib/socket.rb, line 431 def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false) __recvmsg(dlen, flags, clen, scm_rights) end
recvmsg empfängt eine Nachricht über den recvmsg(2)-Systemaufruf blockierend.
maxmesglen ist die maximale Länge von mesg, die empfangen werden soll.
flags ist die bitweise OR von MSG_* Konstanten wie Socket::MSG_PEEK.
maxcontrollen ist die maximale Länge von Controls (Ancillary Data), die empfangen werden sollen.
opts ist ein Options-Hash. Derzeit ist :scm_rights=>bool die einzige Option.
:scm_rights Option gibt an, dass die Anwendung eine SCM_RIGHTS Control-Nachricht erwartet. Wenn der Wert nil oder false ist, erwartet die Anwendung keine SCM_RIGHTS Control-Nachricht. In diesem Fall schließt recvmsg die übergebenen Dateideskriptoren sofort. Dies ist das Standardverhalten.
Wenn der Wert :scm_rights weder nil noch false ist, erwartet die Anwendung eine SCM_RIGHTS Control-Nachricht. In diesem Fall erstellt recvmsg IO-Objekte für jeden Dateideskriptor für die Methode Socket::AncillaryData#unix_rights.
Der Rückgabewert ist ein 4-elementiges Array.
mesg ist ein String der empfangenen Nachricht.
sender_addrinfo ist die Sender-Socket-Adresse für verbindungslose Sockets. Es ist ein Addrinfo-Objekt. Für verbindungsorientierte Sockets wie TCP ist sender_addrinfo plattformabhängig.
rflags sind Flags der empfangenen Nachricht, die die bitweise OR von MSG_* Konstanten wie Socket::MSG_TRUNC darstellen. Sie ist nil, wenn das System einen alten recvmsg-Systemaufruf nach dem Stil 4.3BSD verwendet.
controls sind Ancillary Data, ein Array von Socket::AncillaryData-Objekten wie z. B.
#<Socket::AncillaryData: AF_UNIX SOCKET RIGHTS 7>
maxmesglen und maxcontrollen können nil sein. In diesem Fall wird der Puffer vergrößert, bis die Nachricht nicht mehr abgeschnitten ist. Intern wird MSG_PEEK verwendet. Puffer voll und MSG_CTRUNC werden auf Abschneiden geprüft.
recvmsg kann zur Implementierung von recv_io wie folgt verwendet werden
mesg, sender_sockaddr, rflags, *controls = sock.recvmsg(:scm_rights=>true) controls.each {|ancdata| if ancdata.cmsg_is?(:SOCKET, :RIGHTS) return ancdata.unix_rights[0] end }
Source
# File ext/socket/lib/socket.rb, line 447 def recvmsg_nonblock(dlen = nil, flags = 0, clen = nil, scm_rights: false, exception: true) __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception) end
recvmsg empfängt eine Nachricht über den recvmsg(2)-Systemaufruf nicht-blockierend.
Es ist ähnlich wie BasicSocket#recvmsg, aber das Nicht-Blockierungsflag wird vor dem Systemaufruf gesetzt und der Systemaufruf wird nicht wiederholt.
Durch die Angabe eines Keyword-Arguments exception auf false können Sie angeben, dass recvmsg_nonblock keine IO::WaitReadable-Ausnahme auslösen, sondern das Symbol :wait_readable zurückgeben soll.
Source
static VALUE
bsock_remote_address(VALUE sock)
{
union_sockaddr buf;
socklen_t len = (socklen_t)sizeof buf;
socklen_t len0 = len;
rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getpeername(fptr->fd, &buf.addr, &len) < 0)
rb_sys_fail("getpeername(2)");
if (len0 < len) len = len0;
return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
}
Gibt ein Addrinfo-Objekt für die Remote-Adresse zurück, die mit getpeername abgerufen wurde.
Beachten Sie, dass addrinfo.protocol mit 0 gefüllt ist.
TCPSocket.open("www.ruby-lang.org", 80) {|s| p s.remote_address #=> #<Addrinfo: 221.186.184.68:80 TCP> } TCPServer.open("127.0.0.1", 1728) {|serv| c = TCPSocket.new("127.0.0.1", 1728) s = serv.accept p s.remote_address #=> #<Addrinfo: 127.0.0.1:36504 TCP> }
Source
VALUE
rsock_bsock_send(int argc, VALUE *argv, VALUE socket)
{
struct rsock_send_arg arg;
VALUE flags, to;
rb_io_t *fptr;
rb_blocking_function_t *func;
const char *funcname;
rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
StringValue(arg.mesg);
if (!NIL_P(to)) {
SockAddrStringValue(to);
to = rb_str_new4(to);
arg.to = (struct sockaddr *)RSTRING_PTR(to);
arg.tolen = RSTRING_SOCKLEN(to);
func = rsock_sendto_blocking;
funcname = "sendto(2)";
}
else {
func = rsock_send_blocking;
funcname = "send(2)";
}
RB_IO_POINTER(socket, fptr);
arg.fd = fptr->fd;
arg.flags = NUM2INT(flags);
while (true) {
#ifdef RSOCK_WAIT_BEFORE_BLOCKING
rb_io_wait(socket, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil);
#endif
ssize_t n = (ssize_t)rb_io_blocking_region(fptr, func, &arg);
if (n >= 0) return SSIZET2NUM(n);
if (rb_io_maybe_wait_writable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) {
continue;
}
rb_sys_fail(funcname);
}
}
sendet mesg über basicsocket.
mesg sollte ein String sein.
flags sollte eine bitweise OR-Verknüpfung der Socket::MSG_* Konstanten sein.
dest_sockaddr sollte ein gepackter sockaddr-String oder ein addrinfo sein.
TCPSocket.open("localhost", 80) {|s| s.send "GET / HTTP/1.0\r\n\r\n", 0 p s.read }
Source
# File ext/socket/lib/socket.rb, line 307 def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls) __sendmsg(mesg, flags, dest_sockaddr, controls) end
sendmsg sendet eine Nachricht über den sendmsg(2)-Systemaufruf blockierend.
mesg ist der zu sendende String.
flags ist die bitweise OR von MSG_* Konstanten wie Socket::MSG_OOB.
dest_sockaddr ist die Ziel-Socket-Adresse für verbindungslose Sockets. Es sollte ein sockaddr sein, z. B. das Ergebnis von Socket.sockaddr_in. Ein Addrinfo-Objekt kann ebenfalls verwendet werden.
controls ist eine Liste von Ancillary Data. Das Element von controls sollte ein Socket::AncillaryData oder ein 3-elementiges Array sein. Das 3-elementige Array sollte cmsg_level, cmsg_type und data enthalten.
Der Rückgabewert, numbytes_sent, ist eine Ganzzahl, die die Anzahl der gesendeten Bytes angibt.
sendmsg kann zur Implementierung von send_io wie folgt verwendet werden
# use Socket::AncillaryData. ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, io.fileno) sock.sendmsg("a", 0, nil, ancdata) # use 3-element array. ancdata = [:SOCKET, :RIGHTS, [io.fileno].pack("i!")] sock.sendmsg("\0", 0, nil, ancdata)
Source
# File ext/socket/lib/socket.rb, line 323 def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls, exception: true) __sendmsg_nonblock(mesg, flags, dest_sockaddr, controls, exception) end
sendmsg_nonblock sendet eine Nachricht über den sendmsg(2)-Systemaufruf nicht-blockierend.
Es ist ähnlich wie BasicSocket#sendmsg, aber das Nicht-Blockierungsflag wird vor dem Systemaufruf gesetzt und der Systemaufruf wird nicht wiederholt.
Durch die Angabe eines Keyword-Arguments exception auf false können Sie angeben, dass sendmsg_nonblock keine IO::WaitWritable-Ausnahme auslösen, sondern das Symbol :wait_writable zurückgeben soll.
Source
static VALUE
bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
{
VALUE lev, optname, val;
int family, level, option;
rb_io_t *fptr;
int i;
char *v;
int vlen;
if (argc == 1) {
lev = rb_funcall(argv[0], rb_intern("level"), 0);
optname = rb_funcall(argv[0], rb_intern("optname"), 0);
val = rb_funcall(argv[0], rb_intern("data"), 0);
}
else {
rb_scan_args(argc, argv, "30", &lev, &optname, &val);
}
GetOpenFile(sock, fptr);
family = rsock_getfamily(fptr);
level = rsock_level_arg(family, lev);
option = rsock_optname_arg(family, level, optname);
switch (TYPE(val)) {
case T_FIXNUM:
i = FIX2INT(val);
goto numval;
case T_FALSE:
i = 0;
goto numval;
case T_TRUE:
i = 1;
numval:
v = (char*)&i; vlen = (int)sizeof(i);
break;
default:
StringValue(val);
v = RSTRING_PTR(val);
vlen = RSTRING_SOCKLEN(val);
break;
}
rb_io_check_closed(fptr);
if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
rsock_sys_fail_path("setsockopt(2)", fptr->pathv);
return INT2FIX(0);
}
Setzt eine Socket-Option. Diese sind protokoll- und systemspezifisch. Informationen finden Sie in der Dokumentation Ihres lokalen Systems.
Parameter
-
levelist eine Ganzzahl, normalerweise eine der SOL_-Konstanten wie Socket::SOL_SOCKET oder eine Protokollebene. Ein String oder Symbol des Namens, möglicherweise ohne Präfix, wird ebenfalls akzeptiert. -
optnameist eine Ganzzahl, normalerweise eine der SO_-Konstanten wie Socket::SO_REUSEADDR. Ein String oder Symbol des Namens, möglicherweise ohne Präfix, wird ebenfalls akzeptiert. -
optvalist der Wert der Option. Er wird an das zugrundeliegende setsockopt() als Zeiger auf eine bestimmte Anzahl von Bytes übergeben. Wie dies geschieht, hängt vom Typ ab.-
Integer: Der Wert wird einer Ganzzahl zugewiesen, und ein Zeiger auf die Ganzzahl wird mit der Länge sizeof(int) übergeben.
-
true oder false: 1 oder 0 (jeweils) wird einer Ganzzahl zugewiesen, und die Ganzzahl wird wie für einen
Integerübergeben. Beachten Sie, dassfalse, nichtnil, übergeben werden muss. -
String: Die Daten und die Länge des Strings werden an den Socket übergeben.
-
-
socketoptionist eine Instanz vonSocket::Option
Beispiele
Einige Socket-Optionen sind Ganzzahlen mit booleschen Werten. In diesem Fall kann setsockopt wie folgt aufgerufen werden
sock.setsockopt(:SOCKET, :REUSEADDR, true) sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
Einige Socket-Optionen sind Ganzzahlen mit numerischen Werten. In diesem Fall kann setsockopt wie folgt aufgerufen werden
sock.setsockopt(:IP, :TTL, 255) sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255) sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
Optionswerte können Strukturen sein. Deren Übergabe kann komplex sein, da sie die Untersuchung Ihrer System-Header erfordert, um die korrekte Definition zu ermitteln. Ein Beispiel ist ein ip_mreq, das in Ihren System-Headern wie folgt definiert sein kann:
struct ip_mreq { struct in_addr imr_multiaddr; struct in_addr imr_interface; };
In diesem Fall kann setsockopt wie folgt aufgerufen werden
optval = IPAddr.new("224.0.0.251").hton + IPAddr.new(Socket::INADDR_ANY, Socket::AF_INET).hton sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval)
Source
static VALUE
bsock_shutdown(int argc, VALUE *argv, VALUE sock)
{
VALUE howto;
int how;
rb_io_t *fptr;
rb_scan_args(argc, argv, "01", &howto);
if (howto == Qnil)
how = SHUT_RDWR;
else {
how = rsock_shutdown_how_arg(howto);
if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
}
}
GetOpenFile(sock, fptr);
if (shutdown(fptr->fd, how) == -1)
rb_sys_fail("shutdown(2)");
return INT2FIX(0);
}
Ruft den shutdown(2)-Systemaufruf auf.
s.shutdown(Socket::SHUT_RD) verhindert weitere Lesevorgänge.
s.shutdown(Socket::SHUT_WR) verhindert weitere Schreibvorgänge.
s.shutdown(Socket::SHUT_RDWR) verhindert weitere Lese- und Schreibvorgänge.
how kann ein Symbol oder ein String sein
-
:RD, :SHUT_RD, “RD” und “SHUT_RD” werden als Socket::SHUT_RD akzeptiert.
-
:WR, :SHUT_WR, “WR” und “SHUT_WR” werden als Socket::SHUT_WR akzeptiert.
-
:RDWR, :SHUT_RDWR, “RDWR” und “SHUT_RDWR” werden als Socket::SHUT_RDWR akzeptiert.
UNIXSocket.pair{|s1, s2|s1.puts "ping" s1.shutdown(:WR) p s2.read #=> "ping\n" s2.puts "pong" s2.close p s1.read #=> "pong\n"
}