BasicSocket
class BasicSocket
Parent:IO
BasicSocket是所有Socket类的超类。
公共类方法
do_not_reverse_lookup → true or false Show source
获取global :: do_not_reverse_lookup标志。
BasicSocket.do_not_reverse_lookup #=> false
static VALUE
bsock_do_not_rev_lookup(void)
{
return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
}
do_not_reverse_lookup = bool Show source
设置global :: do_not_reverse_lookup标志。
该标志用于每个套接字的初始值:: do_not_reverse_lookup。
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
static VALUE
bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
{
rsock_do_not_reverse_lookup = RTEST(val
return val;
}
for_fd(fd) → basicsocket Show source
返回一个包含文件描述符fd
的套接字对象。
# If invoked by inetd, STDIN/STDOUT/STDERR is a socket.
STDIN_SOCK = Socket.for_fd(STDIN.fileno)
p STDIN_SOCK.remote_address
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;
}
公共实例方法
close_read → nil Show source
不允许使用关机系统调用进一步阅读。
s1, s2 = UNIXSocket.pair
s1.close_read
s2.puts #=> Broken pipe (Errno::EPIPE)
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 Show source
禁止使用关机系统调用进一步写入。
UNIXSocket.pair {|s1, s2|
s1.print "ping"
s1.close_write
p s2.read #=> "ping"
s2.print "pong"
s2.close
p s1.read #=> "pong"
}
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() Show source
返回适合本地机器连接的套接字地址。
此方法返回自我
.local_address,除了以下条件。
- IPv4未指定地址(0.0.0.0)被替换为IPv4回送地址(127.0.0.1)。
如果本地地址不适合连接,则引发SocketError。IPv4和IPv6地址哪个端口是0不适合连接。没有路径的Unix域套接字不适合连接。
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>]
}
}
# File ext/socket/lib/socket.rb, line 250
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 → true or false Show source
获取basicsocket
的:: do_not_reverse_lookup标志。
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
}
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 Show source
设置basicsocket
的:: do_not_reverse_lookup标志。
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"]
}
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 → euid, egid()
返回UNIX套接字对等体上的用户和组。结果是包含有效uid和有效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
}
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 → sockaddr Show source
以sockaddr字符串的形式返回套接字的远程地址。
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"
}
如果Addrinfo对象优先于二进制字符串,请使用#remote_address。
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 → sockaddr Show source
以sockaddr字符串的形式返回套接字的本地地址。
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"
}
如果Addrinfo对象优先于二进制字符串,请使用#local_address。
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) → socketoption Show source
获取套接字选项。这些是协议和系统特定的,请参阅本地系统文档以获取详细信息。该选项作为Socket :: Option对象返回。
参数
level
是一个整数,通常是SOL_常量之一,例如Socket :: SOL_SOCKET或协议级别。该名称的字符串或符号,可能没有前缀,也被接受。
例子
一些套接字选项是带有布尔值的整数,在这种情况下,getsockopt可以这样调用:
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
一些套接字选项是带有数字值的整数,在这种情况下,getsockopt可以这样调用:
ipttl = sock.getsockopt(:IP, :TTL).int
optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
ipttl = optval.unpack("i")[0]
选项值可能是结构。解码它们可能很复杂,因为它涉及检查系统标题以确定正确的定义。一个例子是+ struct linger +,它可以在系统头文件中定义为:
struct linger {
int l_onoff;
int l_linger;
};
在这种情况下,getsockopt可以这样调用:
# 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
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 → addrinfo Show source
返回由getsockname获取的本地地址的Addrinfo对象。
请注意,addrinfo.protocol由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>
}
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]) → mesg Show source
接收消息。
maxlen
是要接收的最大字节数。
标志
应该是Socket :: MSG_ *常量的按位或。
即使outbuf
在开始时不是空的,outbuf
也只会包含方法调用后接收到的数据。
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"
}
static VALUE
bsock_recv(int argc, VALUE *argv, VALUE sock)
{
return rsock_s_recvfrom(sock, argc, argv, RECV_RECV
}
recv_nonblock(maxlen [,flags [,buf,options]])→mesg显示源
在为基础文件描述符设置了O_NONBLOCK后,接收使用recvfrom(2)时的maxlen
字节socket
。标志
是零个或多个MSG_
选项。结果mesg
是收到的数据。
当recvfrom(2)返回0时,#recv_nonblock返回一个空字符串作为数据。含义取决于套接字:TCP上的EOF,UDP上的空数据包等。
参数
maxlen
- 从套接字接收的字节数
例
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
如果对recv_nonblock
的调用失败,请参考Socket#recvfrom获取可能抛出的异常。
#recv_nonblock可能引发与recvfrom(2)失败相对应的任何错误,包括Errno :: EWOULDBLOCK。
如果该异常是Errno :: EWOULDBLOCK或Errno :: EAGAIN,则它由IO :: WaitReadable扩展。所以IO :: WaitReadable可以用来挽救重试recv_nonblock的异常。
通过指定关键字参数异常
来false
,你可以指出#recv_nonblock应该不会引发IO :: WaitReadable异常
,但返回的符号:wait_readable
来代替。
详见
- Socket#recvfrom
# File ext/socket/lib/socket.rb, line 369
def recv_nonblock(len, flag = 0, str = nil, exception: true)
__recv_nonblock(len, flag, str, exception)
end
recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) → mesg, sender_addrinfo, rflags, *controls()
recvmsg以阻塞方式使用recvmsg(2)系统调用接收消息。
maxmesglen
是mesg接收的最大长度。
标志
是MSG_ *常数的按位OR,例如Socket :: MSG_PEEK。
maxcontrollen
是要接收的控件(辅助数据)的最大长度。
opts是选项散列。目前:scm_rights => bool是唯一的选择。
:scm_rights选项指定应用程序需要SCM_RIGHTS控制消息。如果值为零或为假,应用程序不会期望SCM_RIGHTS控制消息。在这种情况下,recvmsg会立即关闭传递的文件描述符。这是默认行为。
如果:scm_rights值既不是零也不是false,应用程序需要SCM_RIGHTS控制消息。在这种情况下,recvmsg会为Socket :: AncillaryData#unix_rights方法的每个文件描述符创建IO对象。
返回值是4元素数组。
mesg
是接收到的消息的字符串。
sender_addrinfo
是无连接套接字的发件人套接字地址。它是一个Addrinfo对象。对于面向连接的套接字(如TCP),sender_addrinfo
是平台相关的。
rflags
是接收到的消息上的标志,它是MSG_ *常数(如Socket :: MSG_TRUNC)的按位或运算。如果系统使用4.3BSD风格的旧recvmsg系统调用,则为零。
控件
是辅助数据,它是Socket :: AncillaryData对象的数组,如:
#<Socket::AncillaryData: AF_UNIX SOCKET RIGHTS 7>
maxmesglen
和maxcontrollen
可以为零。在这种情况下,缓冲区将会增长,直到消息未被截断。在内部使用MSG_PEEK。缓冲区满和MSG_CTRUNC被检查截断。
recvmsg可以用来实现recv_io,如下所示:
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
}
# File ext/socket/lib/socket.rb, line 424
def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false)
__recvmsg(dlen, flags, clen, scm_rights)
end
recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) → data, sender_addrinfo, rflags, *controls()
recvmsg以非阻塞方式使用recvmsg(2)系统调用接收消息。
它与#recvmsg类似,但在系统调用之前设置了非阻塞标志,并且不会重试系统调用。
通过指定关键字参数异常
来false
,你可以指出#recvmsg_nonblock应该不会引发IO :: WaitReadable异常
,但返回的符号:wait_readable
来代替。
# File ext/socket/lib/socket.rb, line 440
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 → addrinfo Show source
返回由getpeername获取的远程地址的Addrinfo对象。
请注意,addrinfo.protocol由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>
}
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) → numbytes_sent Show source
通过basicsocket
发送mesg
。
mesg
应该是一个字符串。
标志
应该是Socket :: MSG_ *常量的按位或。
dest_sockaddr
应该是一个打包的sockaddr字符串或一个addrinfo。
TCPSocket.open("localhost", 80) {|s|
s.send "GET / HTTP/1.0\r\n\r\n", 0
p s.read
}
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)→numbytes_sent显示源代码
sendmsg使用sendmsg(2)系统调用以阻塞方式发送消息。
mesg
是要发送的字符串。
标志
是MSG_ *常数(如Socket :: MSG_OOB)的或位。
dest_sockaddr
是无连接套接字的目标套接字地址。它应该是一个sockaddr,比如Socket.sockaddr_in的结果。Addrinfo对象也可以使用。
控件
是辅助数据的列表。控件
的元素应该是Socket :: AncillaryData或3个元素的数组。3元素数组应该包含cmsg_level,cmsg_type和data。
返回值numbytes_sent
是一个整数,它是发送的字节数。
sendmsg可以用来实现send_io,如下所示:
# 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)
# File ext/socket/lib/socket.rb, line 302
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, opts={}) → numbytes_sent Show source
#sendmsg_nonblock以非阻塞方式使用sendmsg(2)系统调用发送消息。
它与#sendmsg类似,但在系统调用之前设置了非阻塞标志,并且不会重试系统调用。
通过指定关键字参数异常
来false
,你可以指出#sendmsg_nonblock应该不会引发IO :: WaitWritable异常
,但返回的符号:wait_writable
来代替。
# File ext/socket/lib/socket.rb, line 318
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) Show source
setsockopt(socketoption)
设置套接字选项。这些是协议和系统特定的,请参阅本地系统文档以获取详细信息。
参数
level
是一个整数,通常是SOL_常量之一,例如Socket :: SOL_SOCKET或协议级别。该名称的字符串或符号,可能没有前缀,也被接受。
- Integer: 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 an [Integer](integer). Note that `false` must be passed, not `nil`.
- String: the string's data and length is passed to the socket.
socketoption
is an instance of Socket::Option
例子
一些套接字选项是带有布尔值的整数,在这种情况下,setsockopt可以这样调用:
sock.setsockopt(:SOCKET, :REUSEADDR, true)
sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
sock.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true))
一些套接字选项是带有数字值的整数,在这种情况下,setsockopt可以这样调用:
sock.setsockopt(:IP, :TTL, 255)
sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255)
sock.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255))
选项值可能是结构。传递它们可能很复杂,因为它涉及检查系统标题以确定正确的定义。一个例子是ip_mreq
,它可以在你的系统头文件中定义为:
struct ip_mreq {
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
在这种情况下,setsockopt可以这样调用:
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)
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 Show source
调用关机(2)系统调用。
s.shutdown(Socket :: SHUT_RD)不允许进一步读取。
s.shutdown(Socket :: SHUT_WR)不允许进一步写入。
s.shutdown(Socket :: SHUT_RDWR)不允许进一步读写。
如何
可以是符号或字符串:
- :RD, :SHUT_RD, “RD” and “SHUT_RD” are accepted as Socket::SHUT_RD.
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
}