Class: BasicSocket
- Inherits:
-
IO
- Object
- IO
- BasicSocket
- Defined in:
- basicsocket.c,
basicsocket.c,
lib/socket.rb
Overview
BasicSocket is the super class for all the Socket classes.
Direct Known Subclasses
Class Method Summary collapse
-
.do_not_reverse_lookup ⇒ Boolean
Gets the global do_not_reverse_lookup flag.
-
.do_not_reverse_lookup=(bool) ⇒ Object
Sets the global do_not_reverse_lookup flag.
-
.for_fd(fd) ⇒ Object
Returns a socket object which contains the file descriptor, fd.
Instance Method Summary collapse
-
#close_read ⇒ nil
Disallows further read using shutdown system call.
-
#close_write ⇒ nil
Disallows further write using shutdown system call.
-
#connect_address ⇒ Object
Returns an address of the socket suitable for connect in the local machine.
-
#do_not_reverse_lookup ⇒ Boolean
Gets the do_not_reverse_lookup flag of basicsocket.
-
#do_not_reverse_lookup=(bool) ⇒ Object
Sets the do_not_reverse_lookup flag of basicsocket.
-
#getpeereid ⇒ Array
Returns the user and group on the peer of the UNIX socket.
-
#getpeername ⇒ Object
Returns the remote address of the socket as a sockaddr string.
-
#getsockname ⇒ Object
Returns the local address of the socket as a sockaddr string.
-
#getsockopt(level, optname) ⇒ Object
Gets a socket option.
-
#local_address ⇒ Object
Returns an Addrinfo object for local address obtained by getsockname.
-
#recv(maxlen[, flags[, outbuf]]) ⇒ Object
Receives a message.
-
#recv_nonblock(len, flag = 0, str = nil, exception: true) ⇒ Object
call-seq: basicsocket.recv_nonblock(maxlen [, flags [, buf [, options ]]]) => mesg.
-
#recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false) ⇒ Object
call-seq: basicsocket.recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) => [mesg, sender_addrinfo, rflags, *controls].
-
#recvmsg_nonblock(dlen = nil, flags = 0, clen = nil, scm_rights: false, exception: true) ⇒ Object
call-seq: basicsocket.recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) => [data, sender_addrinfo, rflags, *controls].
-
#remote_address ⇒ Object
Returns an Addrinfo object for remote address obtained by getpeername.
-
#send(mesg, flags[, dest_sockaddr]) ⇒ Object
send mesg via basicsocket.
-
#sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls) ⇒ Object
call-seq: basicsocket.sendmsg(mesg, flags=0, dest_sockaddr=nil, *controls) => numbytes_sent.
-
#sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls, exception: true) ⇒ Object
call-seq: basicsocket.sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) => numbytes_sent.
-
#setsockopt(*args) ⇒ Object
Sets a socket option.
-
#shutdown([how]) ⇒ 0
Calls shutdown(2) system call.
Class Method Details
.do_not_reverse_lookup ⇒ Boolean
Gets the global do_not_reverse_lookup flag.
BasicSocket.do_not_reverse_lookup #=> false
657 658 659 660 661 |
# File 'basicsocket.c', line 657
static VALUE
bsock_do_not_rev_lookup(void)
{
return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
}
|
.do_not_reverse_lookup=(bool) ⇒ Object
Sets the global do_not_reverse_lookup flag.
The flag is used for initial value of do_not_reverse_lookup for each socket.
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
679 680 681 682 683 684 |
# File 'basicsocket.c', line 679
static VALUE
bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
{
rsock_do_not_reverse_lookup = RTEST(val);
return val;
}
|
.for_fd(fd) ⇒ Object
Returns a socket object which contains the file descriptor, fd.
# If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
STDIN_SOCK = Socket.for_fd(STDIN.fileno)
p STDIN_SOCK.remote_address
24 25 26 27 28 29 30 31 32 33 |
# File 'basicsocket.c', line 24
static VALUE
bsock_s_for_fd(VALUE klass, VALUE fd)
{
rb_io_t *fptr;
VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd));
GetOpenFile(sock, fptr);
return sock;
}
|
Instance Method Details
#close_read ⇒ nil
Disallows further read using shutdown system call.
s1, s2 = UNIXSocket.pair
s1.close_read
s2.puts #=> Broken pipe (Errno::EPIPE)
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'basicsocket.c', line 95
static VALUE
bsock_close_read(VALUE sock)
{
rb_io_t *fptr;
GetOpenFile(sock, fptr);
shutdown(fptr->fd, 0);
if (!(fptr->mode & FMODE_WRITABLE)) {
return rb_io_close(sock);
}
fptr->mode &= ~FMODE_READABLE;
return Qnil;
}
|
#close_write ⇒ nil
Disallows further write using shutdown system call.
UNIXSocket.pair {|s1, s2|
s1.print "ping"
s1.close_write
p s2.read #=> "ping"
s2.print "pong"
s2.close
p s1.read #=> "pong"
}
125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'basicsocket.c', line 125
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, 1);
fptr->mode &= ~FMODE_WRITABLE;
return Qnil;
}
|
#connect_address ⇒ Object
Returns an address of the socket suitable for connect in the local machine.
This method returns self.local_address, except following condition.
-
IPv4 unspecified address (0.0.0.0) is replaced by IPv4 loopback address (127.0.0.1).
-
IPv6 unspecified address (::) is replaced by IPv6 loopback address (::1).
If the local address is not suitable for connect, SocketError is raised. IPv4 and IPv6 address which port is 0 is not suitable for connect. Unix domain socket which has no path is not suitable for connect.
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>]
}
}
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File '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 |
#do_not_reverse_lookup ⇒ Boolean
Gets the do_not_reverse_lookup flag of basicsocket.
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
}
577 578 579 580 581 582 583 584 |
# File 'basicsocket.c', line 577
static VALUE
bsock_do_not_reverse_lookup(VALUE sock)
{
rb_io_t *fptr;
GetOpenFile(sock, fptr);
return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
}
|
#do_not_reverse_lookup=(bool) ⇒ Object
Sets the do_not_reverse_lookup flag of 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"]
}
600 601 602 603 604 605 606 607 608 609 610 611 612 613 |
# File 'basicsocket.c', line 600
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;
}
|
#getpeereid ⇒ Array
Returns the user and group on the peer of the UNIX socket. The result is a two element array which contains the effective uid and the effective gid.
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
}
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
# File 'basicsocket.c', line 409
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
}
|
#getpeername ⇒ Object
Returns the remote address of the socket as a sockaddr string.
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"
}
If Addrinfo object is preferred over the binary string, use BasicSocket#remote_address.
371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'basicsocket.c', line 371
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);
}
|
#getsockname ⇒ Object
Returns the local address of the socket as a sockaddr string.
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"
}
If Addrinfo object is preferred over the binary string, use BasicSocket#local_address.
340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'basicsocket.c', line 340
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);
}
|
#getsockopt(level, optname) ⇒ Object
Gets a socket option. These are protocol and system specific, see your local system documentation for details. The option is returned as a Socket::Option object.
Parameters
-
level
is an integer, usually one of the SOL_ constants such as Socket::SOL_SOCKET, or a protocol level. A string or symbol of the name, possibly without prefix, is also accepted. -
optname
is an integer, usually one of the SO_ constants, such as Socket::SO_REUSEADDR. A string or symbol of the name, possibly without prefix, is also accepted.
Examples
Some socket options are integers with boolean values, in this case #getsockopt could be called like this:
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
Some socket options are integers with numeric values, in this case #getsockopt could be called like this:
ipttl = sock.getsockopt(:IP, :TTL).int
optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
ipttl = optval.unpack("i")[0]
Option values may be structs. Decoding them can be complex as it involves examining your system headers to determine the correct definition. An example is a struct linger, which may be defined in your system headers as:
struct linger {
int l_onoff;
int l_linger;
};
In this case #getsockopt could be called like this:
# 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
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'basicsocket.c', line 303
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;
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));
}
|
#local_address ⇒ Object
Returns an Addrinfo object for local address obtained by getsockname.
Note that addrinfo.protocol is filled by 0.
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>
}
461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
# File 'basicsocket.c', line 461
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);
}
|
#recv(maxlen[, flags[, outbuf]]) ⇒ Object
Receives a message.
maxlen is the maximum number of bytes to receive.
flags should be a bitwise OR of Socket::MSG_* constants.
outbuf will contain only the received data after the method call even if it is not empty at the beginning.
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"
}
636 637 638 639 640 |
# File 'basicsocket.c', line 636
static VALUE
bsock_recv(int argc, VALUE *argv, VALUE sock)
{
return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
}
|
#recv_nonblock(len, flag = 0, str = nil, exception: true) ⇒ Object
call-seq: basicsocket.recv_nonblock(maxlen [, flags [, buf [, options ]]]) => mesg
Receives up to maxlen bytes from socket
using recvfrom(2) after O_NONBLOCK is set for the underlying file descriptor. flags is zero or more of the MSG_
options. The result, mesg, is the data received.
When recvfrom(2) returns 0, Socket#recv_nonblock returns an empty string as data. The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
Parameters
-
maxlen
- the number of bytes to receive from the socket -
flags
- zero or more of theMSG_
options -
options
- keyword hash, supporting ‘exception: false`
Example
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() retry end
Refer to Socket#recvfrom for the exceptions that may be thrown if the call to recv_nonblock fails.
BasicSocket#recv_nonblock may raise any error corresponding to recvfrom(2) failure, including Errno::EWOULDBLOCK.
If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN, it is extended by IO::WaitReadable. So IO::WaitReadable can be used to rescue the exceptions for retrying recv_nonblock.
By specifying ‘exception: false`, the options hash allows you to indicate that recv_nonblock should not raise an IO::WaitWritable exception, but return the symbol :wait_writable instead.
See
-
Socket#recvfrom
374 375 376 |
# File 'lib/socket.rb', line 374 def recv_nonblock(len, flag = 0, str = nil, exception: true) __recv_nonblock(len, flag, str, exception) end |
#recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false) ⇒ Object
call-seq:
basicsocket.recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) => [mesg, sender_addrinfo, rflags, *controls]
recvmsg receives a message using recvmsg(2) system call in blocking manner.
maxmesglen is the maximum length of mesg to receive.
flags is bitwise OR of MSG_* constants such as Socket::MSG_PEEK.
maxcontrollen is the maximum length of controls (ancillary data) to receive.
opts is option hash. Currently :scm_rights=>bool is the only option.
:scm_rights option specifies that application expects SCM_RIGHTS control message. If the value is nil or false, application don’t expects SCM_RIGHTS control message. In this case, recvmsg closes the passed file descriptors immediately. This is the default behavior.
If :scm_rights value is neither nil nor false, application expects SCM_RIGHTS control message. In this case, recvmsg creates IO objects for each file descriptors for Socket::AncillaryData#unix_rights method.
The return value is 4-elements array.
mesg is a string of the received message.
sender_addrinfo is a sender socket address for connection-less socket. It is an Addrinfo object. For connection-oriented socket such as TCP, sender_addrinfo is platform dependent.
rflags is a flags on the received message which is bitwise OR of MSG_* constants such as Socket::MSG_TRUNC. It will be nil if the system uses 4.3BSD style old recvmsg system call.
controls is ancillary data which is an array of Socket::AncillaryData objects such as:
#<Socket::AncillaryData: AF_UNIX SOCKET RIGHTS 7>
maxmesglen and maxcontrollen can be nil. In that case, the buffer will be grown until the message is not truncated. Internally, MSG_PEEK is used. Buffer full and MSG_CTRUNC are checked for truncation.
recvmsg can be used to implement recv_io as follows:
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
}
429 430 431 |
# File 'lib/socket.rb', line 429 def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false) __recvmsg(dlen, flags, clen, scm_rights) end |
#recvmsg_nonblock(dlen = nil, flags = 0, clen = nil, scm_rights: false, exception: true) ⇒ Object
call-seq:
basicsocket.recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) => [data, sender_addrinfo, rflags, *controls]
recvmsg receives a message using recvmsg(2) system call in non-blocking manner.
It is similar to BasicSocket#recvmsg but non-blocking flag is set before the system call and it doesn’t retry the system call.
By specifying ‘exception: false`, the opts hash allows you to indicate that recvmsg_nonblock should not raise an IO::WaitWritable exception, but return the symbol :wait_writable instead.
445 446 447 448 |
# File 'lib/socket.rb', line 445 def recvmsg_nonblock(dlen = nil, flags = 0, clen = nil, scm_rights: false, exception: true) __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception) end |
#remote_address ⇒ Object
Returns an Addrinfo object for remote address obtained by getpeername.
Note that addrinfo.protocol is filled by 0.
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>
}
495 496 497 498 499 500 501 502 503 504 505 506 507 508 |
# File 'basicsocket.c', line 495
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);
}
|
#send(mesg, flags[, dest_sockaddr]) ⇒ Object
send mesg via basicsocket.
mesg should be a string.
flags should be a bitwise OR of Socket::MSG_* constants.
dest_sockaddr should be a packed sockaddr string or an addrinfo.
TCPSocket.open("localhost", 80) {|s|
s.send "GET / HTTP/1.0\r\n\r\n", 0
p s.read
}
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
# File 'basicsocket.c', line 527
VALUE
rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
{
struct rsock_send_arg arg;
VALUE flags, to;
rb_io_t *fptr;
int n;
rb_blocking_function_t *func;
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;
}
else {
func = rsock_send_blocking;
}
GetOpenFile(sock, fptr);
arg.fd = fptr->fd;
arg.flags = NUM2INT(flags);
while (rsock_maybe_fd_writable(arg.fd),
(n = (int)BLOCKING_REGION_FD(func, &arg)) < 0) {
if (rb_io_wait_writable(arg.fd)) {
continue;
}
rb_sys_fail("send(2)");
}
return INT2FIX(n);
}
|
#sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls) ⇒ Object
call-seq:
basicsocket.sendmsg(mesg, flags=0, dest_sockaddr=nil, *controls) => numbytes_sent
sendmsg sends a message using sendmsg(2) system call in blocking manner.
mesg is a string to send.
flags is bitwise OR of MSG_* constants such as Socket::MSG_OOB.
dest_sockaddr is a destination socket address for connection-less socket. It should be a sockaddr such as a result of Socket.sockaddr_in. An Addrinfo object can be used too.
controls is a list of ancillary data. The element of controls should be Socket::AncillaryData or 3-elements array. The 3-element array should contains cmsg_level, cmsg_type and data.
The return value, numbytes_sent is an integer which is the number of bytes sent.
sendmsg can be used to implement send_io as follows:
# 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)
307 308 309 |
# File 'lib/socket.rb', line 307 def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls) __sendmsg(mesg, flags, dest_sockaddr, controls) end |
#sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls, exception: true) ⇒ Object
call-seq:
basicsocket.sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) => numbytes_sent
sendmsg_nonblock sends a message using sendmsg(2) system call in non-blocking manner.
It is similar to BasicSocket#sendmsg but the non-blocking flag is set before the system call and it doesn’t retry the system call.
By specifying ‘exception: false`, the opts hash allows you to indicate that sendmsg_nonblock should not raise an IO::WaitWritable exception, but return the symbol :wait_writable instead.
323 324 325 326 |
# File '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 |
#setsockopt(level, optname, optval) ⇒ Object #setsockopt(socketoption) ⇒ Object
Sets a socket option. These are protocol and system specific, see your local system documentation for details.
Parameters
-
level
is an integer, usually one of the SOL_ constants such as Socket::SOL_SOCKET, or a protocol level. A string or symbol of the name, possibly without prefix, is also accepted. -
optname
is an integer, usually one of the SO_ constants, such as Socket::SO_REUSEADDR. A string or symbol of the name, possibly without prefix, is also accepted. -
optval
is the value of the option, it is passed to the underlying setsockopt() as a pointer to a certain number of bytes. How this is done depends on the type:-
Fixnum: value is assigned to an int, and a pointer to the int is passed, with length of sizeof(int).
-
true or false: 1 or 0 (respectively) is assigned to an int, and the int is passed as for a Fixnum. Note that
false
must be passed, notnil
. -
String: the string’s data and length is passed to the socket.
-
-
socketoption
is an instance of Socket::Option
Examples
Some socket options are integers with boolean values, in this case #setsockopt could be called like this:
sock.setsockopt(:SOCKET, :REUSEADDR, true)
sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
Some socket options are integers with numeric values, in this case #setsockopt could be called like this:
sock.setsockopt(:IP, :TTL, 255)
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
Option values may be structs. Passing them can be complex as it involves examining your system headers to determine the correct definition. An example is an ip_mreq
, which may be defined in your system headers as:
struct ip_mreq {
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
In this case #setsockopt could be called like this:
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)
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'basicsocket.c', line 197
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);
}
|
#shutdown([how]) ⇒ 0
Calls shutdown(2) system call.
s.shutdown(Socket::SHUT_RD) disallows further read.
s.shutdown(Socket::SHUT_WR) disallows further write.
s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
how can be symbol or string:
-
:RD, :SHUT_RD, “RD” and “SHUT_RD” are accepted as Socket::SHUT_RD.
-
:WR, :SHUT_WR, “WR” and “SHUT_WR” are accepted as Socket::SHUT_WR.
-
:RDWR, :SHUT_RDWR, “RDWR” and “SHUT_RDWR” are accepted as Socket::SHUT_RDWR.
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"
}
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'basicsocket.c', line 62
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);
}
|