Class: Socket
- Inherits:
-
BasicSocket
- Object
- IO
- BasicSocket
- Socket
- Defined in:
- lib/framework/autocomplete/Socket.rb,
lib/framework/_socket.rb
Overview
It is auto-generated content. Do not do required for this file in your application.
Defined Under Namespace
Modules: Constants, WaitReadable, WaitWritable Classes: UDPSource
Constant Summary collapse
- SOCK_STREAM =
1- SOCK_DGRAM =
2- SOCK_RAW =
3- SOCK_RDM =
4- SOCK_SEQPACKET =
5- AF_INET =
2- PF_INET =
2- AF_UNIX =
1- PF_UNIX =
1- AF_IPX =
6- PF_IPX =
6- AF_APPLETALK =
16- PF_APPLETALK =
16- AF_UNSPEC =
0- PF_UNSPEC =
0- AF_IMPLINK =
3- PF_IMPLINK =
3- AF_PUP =
4- PF_PUP =
4- AF_CHAOS =
5- PF_CHAOS =
5- AF_NS =
6- PF_NS =
6- AF_ISO =
7- PF_ISO =
7- AF_OSI =
7- PF_OSI =
7- AF_ECMA =
8- PF_ECMA =
8- AF_DATAKIT =
9- PF_DATAKIT =
9- AF_CCITT =
10- PF_CCITT =
10- AF_SNA =
11- PF_SNA =
11- AF_DLI =
13- PF_DLI =
13- AF_LAT =
14- PF_LAT =
14- AF_HYLINK =
15- PF_HYLINK =
15- AF_NETBIOS =
17- AF_ATM =
22- PF_ATM =
22- AF_MAX =
32- PF_MAX =
32- MSG_OOB =
1- MSG_PEEK =
2- MSG_DONTROUTE =
4- SOL_SOCKET =
65535- IPPROTO_IP =
0- IPPROTO_ICMP =
1- IPPROTO_IGMP =
2- IPPROTO_GGP =
3- IPPROTO_TCP =
6- IPPROTO_PUP =
12- IPPROTO_UDP =
17- IPPROTO_IDP =
22- IPPROTO_ND =
77- IPPROTO_RAW =
255- IPPROTO_MAX =
256- IPPORT_RESERVED =
1024- IPPORT_USERRESERVED =
5000- INADDR_ANY =
0- INADDR_BROADCAST =
-1
- INADDR_LOOPBACK =
-16777215
- INADDR_UNSPEC_GROUP =
-536870912
- INADDR_ALLHOSTS_GROUP =
-536870911
- INADDR_MAX_LOCAL_GROUP =
-536870657
- INADDR_NONE =
-1
- IP_OPTIONS =
1- IP_HDRINCL =
9- IP_TOS =
8- IP_TTL =
7- IP_MULTICAST_IF =
2- IP_MULTICAST_TTL =
3- IP_MULTICAST_LOOP =
4- IP_ADD_MEMBERSHIP =
5- IP_DROP_MEMBERSHIP =
6- SO_DEBUG =
1- SO_REUSEADDR =
4- SO_TYPE =
4104- SO_ERROR =
4103- SO_DONTROUTE =
16- SO_BROADCAST =
32- SO_SNDBUF =
4097- SO_RCVBUF =
4098- SO_KEEPALIVE =
8- SO_OOBINLINE =
256- SO_LINGER =
128- SO_RCVLOWAT =
4100- SO_SNDLOWAT =
4099- SO_RCVTIMEO =
4102- SO_SNDTIMEO =
4101- SO_ACCEPTCONN =
2- SO_USELOOPBACK =
64- TCP_NODELAY =
1- EAI_AGAIN =
11002- EAI_BADFLAGS =
10022- EAI_FAIL =
11003- EAI_FAMILY =
10047- EAI_MEMORY =
8- EAI_NODATA =
11004- EAI_NONAME =
11001- EAI_SERVICE =
10109- EAI_SOCKTYPE =
10044- AI_PASSIVE =
1- AI_CANONNAME =
2- AI_NUMERICHOST =
4- NI_MAXHOST =
1025- NI_MAXSERV =
32- NI_NOFQDN =
1- NI_NUMERICHOST =
2- NI_NAMEREQD =
4- NI_NUMERICSERV =
8- NI_DGRAM =
16- SHUT_RD =
0- SHUT_WR =
1- SHUT_RDWR =
2- IPV6_JOIN_GROUP =
12- IPV6_LEAVE_GROUP =
13- IPV6_MULTICAST_HOPS =
10- IPV6_MULTICAST_IF =
9- IPV6_MULTICAST_LOOP =
11- IPV6_UNICAST_HOPS =
4- IPV6_HOPLIMIT =
21- IPV6_PKTINFO =
19- SEEK_SET =
0- SEEK_CUR =
1- SEEK_END =
2- LOCK_SH =
1- LOCK_EX =
2- LOCK_UN =
8- LOCK_NB =
4- RDONLY =
0- WRONLY =
1- RDWR =
2- APPEND =
8- CREAT =
256- EXCL =
1024- NONBLOCK =
4- TRUNC =
512- BINARY =
32768- FNM_NOESCAPE =
1- FNM_PATHNAME =
2- FNM_DOTMATCH =
4- FNM_CASEFOLD =
8- FNM_SYSCASE =
8
Class Method Summary collapse
-
.accept_loop(*sockets) ⇒ Object
yield socket and client address for each a connection accepted via given sockets.
- .getaddrinfo(rest) ⇒ Object
- .gethostbyaddr(rest) ⇒ Object
- .gethostbyname(req) ⇒ Object
- .gethostname ⇒ Object
- .getnameinfo(rest) ⇒ Object
- .getservbyname(rest) ⇒ Object
- .getservbyport(rest) ⇒ Object
-
.ip_sockets_port0(ai_list, reuseaddr) ⇒ Object
:stopdoc:.
- .pack_sockaddr_in(req, req1) ⇒ Object
- .pair ⇒ Object
- .sockaddr_in(req, req1) ⇒ Object
- .socketpair ⇒ Object
-
.tcp(host, port, *rest) ⇒ Object
:call-seq: Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| … } Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]).
-
.tcp_server_loop(host = nil, port, &b) ⇒ Object
creates a TCP/IP server on port and calls the block for each connection accepted.
-
.tcp_server_sockets(host = nil, port) ⇒ Object
creates TCP/IP server sockets for host and port.
- .tcp_server_sockets_port0(host) ⇒ Object
-
.udp_server_loop(host = nil, port, &b) ⇒ Object
:call-seq: Socket.udp_server_loop(port) {|msg, msg_src| … } Socket.udp_server_loop(host, port) {|msg, msg_src| … }.
-
.udp_server_loop_on(sockets, &b) ⇒ Object
:call-seq: Socket.udp_server_loop_on(sockets) {|msg, msg_src| … }.
-
.udp_server_recv(sockets) ⇒ Object
:call-seq: Socket.udp_server_recv(sockets) {|msg, msg_src| … }.
-
.udp_server_sockets(host = nil, port) ⇒ Object
:call-seq: Socket.udp_server_sockets([host, ] port).
-
.unix(path) ⇒ Object
creates a new socket connected to path using UNIX socket socket.
-
.unix_server_loop(path, &b) ⇒ Object
creates a UNIX socket server on path.
-
.unix_server_socket(path) ⇒ Object
creates a UNIX server socket on path.
- .unpack_sockaddr_in(req) ⇒ Object
Instance Method Summary collapse
- #accept ⇒ Object
-
#accept_nonblock ⇒ Object
call-seq: socket.accept_nonblock() => [client_socket, client_addrinfo].
- #bind(req) ⇒ Object
- #connect(req) ⇒ Object
-
#connect_nonblock(req) ⇒ Object
call-seq: socket.connect_nonblock(remote_sockaddr, [options]) => 0.
-
#ipv6only! ⇒ Object
enable the socket option IPV6_V6ONLY if IPV6_V6ONLY is available.
- #listen(req) ⇒ Object
- #recvfrom(rest) ⇒ Object
-
#recvfrom_nonblock(rest) ⇒ Object
call-seq: socket.recvfrom_nonblock(maxlen[, flags[, outbuf[, opts]]]) => [mesg, sender_addrinfo].
- #sysaccept ⇒ Object
Methods inherited from BasicSocket
#close_read, #close_write, #connect_address, #do_not_reverse_lookup, do_not_reverse_lookup, #do_not_reverse_lookup=, do_not_reverse_lookup=, for_fd, #getpeername, #getsockname, #getsockopt, #recv, #recv_nonblock, #recvmsg, #recvmsg_nonblock, #send, #sendmsg, #sendmsg_nonblock, #setsockopt, #shutdown
Class Method Details
.accept_loop(*sockets) ⇒ Object
yield socket and client address for each a connection accepted via given sockets.
The arguments are a list of sockets. The individual argument should be a socket or an array of sockets.
This method yields the block sequentially. It means that the next connection is not accepted until the block returns. So concurrent mechanism, thread for example, should be used to service multiple clients at a time.
793 794 795 796 797 798 799 800 801 802 803 804 805 806 |
# File 'lib/framework/_socket.rb', line 793 def self.accept_loop(*sockets) # :yield: socket, client_addrinfo sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets" end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end |
.getaddrinfo(rest) ⇒ Object
327 328 |
# File 'lib/framework/autocomplete/Socket.rb', line 327 def self.getaddrinfo(rest) end |
.gethostbyaddr(rest) ⇒ Object
321 322 |
# File 'lib/framework/autocomplete/Socket.rb', line 321 def self.gethostbyaddr(rest) end |
.gethostbyname(req) ⇒ Object
319 320 |
# File 'lib/framework/autocomplete/Socket.rb', line 319 def self.gethostbyname(req) end |
.gethostname ⇒ Object
317 318 |
# File 'lib/framework/autocomplete/Socket.rb', line 317 def self.gethostname end |
.getnameinfo(rest) ⇒ Object
329 330 |
# File 'lib/framework/autocomplete/Socket.rb', line 329 def self.getnameinfo(rest) end |
.getservbyname(rest) ⇒ Object
323 324 |
# File 'lib/framework/autocomplete/Socket.rb', line 323 def self.getservbyname(rest) end |
.getservbyport(rest) ⇒ Object
325 326 |
# File 'lib/framework/autocomplete/Socket.rb', line 325 def self.getservbyport(rest) end |
.ip_sockets_port0(ai_list, reuseaddr) ⇒ Object
:stopdoc:
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 |
# File 'lib/framework/_socket.rb', line 662 def self.ip_sockets_port0(ai_list, reuseaddr) sockets = [] begin sockets.clear port = nil ai_list.each {|ai| begin s = Socket.new(ai.pfamily, ai.socktype, ai.protocol) rescue SystemCallError next end sockets << s s.ipv6only! if ai.ipv6? if reuseaddr s.setsockopt(:SOCKET, :REUSEADDR, 1) end if !port s.bind(ai) port = s.local_address.ip_port else s.bind(ai.family_addrinfo(ai.ip_address, port)) end } rescue Errno::EADDRINUSE sockets.each {|s| s.close } retry rescue Exception sockets.each {|s| s.close } raise end sockets end |
.pack_sockaddr_in(req, req1) ⇒ Object
333 334 |
# File 'lib/framework/autocomplete/Socket.rb', line 333 def self.pack_sockaddr_in(req,req1) end |
.pair ⇒ Object
315 316 |
# File 'lib/framework/autocomplete/Socket.rb', line 315 def self.pair end |
.sockaddr_in(req, req1) ⇒ Object
331 332 |
# File 'lib/framework/autocomplete/Socket.rb', line 331 def self.sockaddr_in(req,req1) end |
.socketpair ⇒ Object
313 314 |
# File 'lib/framework/autocomplete/Socket.rb', line 313 def self.socketpair end |
.tcp(host, port, *rest) ⇒ Object
:call-seq:
Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... }
Socket.tcp(host, port, local_host=nil, local_port=nil, [opts])
creates a new socket object connected to host:port using TCP/IP.
If local_host:local_port is given, the socket is bound to it.
The optional last argument opts is options represented by a hash. opts may have following options:
- :connect_timeout
-
specify the timeout in seconds.
If a block is given, the block is called with the socket. The value of the block is returned. The socket is closed when this method returns.
If no block is given, the socket is returned.
Socket.tcp("www.ruby-lang.org", 80) {|sock|
sock.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n"
sock.close_write
puts sock.read
}
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
# File 'lib/framework/_socket.rb', line 611 def self.tcp(host, port, *rest) # :yield: socket opts = Hash === rest.last ? rest.pop : {} raise ArgumentError, "wrong number of arguments (#{rest.length} for 2)" if 2 < rest.length local_host, local_port = rest last_error = nil ret = nil connect_timeout = opts[:connect_timeout] local_addr_list = nil if local_host != nil || local_port != nil local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil) end Addrinfo.foreach(host, port, nil, :STREAM) {|ai| if local_addr_list local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily } next if !local_addr else local_addr = nil end begin sock = local_addr ? ai.connect_from(local_addr, :timeout => connect_timeout) : ai.connect(:timeout => connect_timeout) rescue SystemCallError last_error = $! next end ret = sock break } if !ret if last_error raise last_error else raise SocketError, "no appropriate local address" end end if block_given? begin yield ret ensure ret.close if !ret.closed? end else ret end end |
.tcp_server_loop(host = nil, port, &b) ⇒ Object
creates a TCP/IP server on port and calls the block for each connection accepted. The block is called with a socket and a client_address as an Addrinfo object.
If host is specified, it is used with port to determine the server addresses.
The socket is not closed when the block returns. So application should close it explicitly.
This method calls the block sequentially. It means that the next connection is not accepted until the block returns. So concurrent mechanism, thread for example, should be used to service multiple clients at a time.
Note that Addrinfo.getaddrinfo is used to determine the server socket addresses. When Addrinfo.getaddrinfo returns two or more addresses, IPv4 and IPv6 address for example, all of them are used. Socket.tcp_server_loop succeeds if one socket can be used at least.
# Sequential echo server.
# It services only one client at a time.
Socket.tcp_server_loop(16807) {|sock, client_addrinfo|
begin
IO.copy_stream(sock, sock)
ensure
sock.close
end
}
# Threaded echo server
# It services multiple clients at a time.
# Note that it may accept connections too much.
Socket.tcp_server_loop(16807) {|sock, client_addrinfo|
Thread.new {
begin
IO.copy_stream(sock, sock)
ensure
sock.close
end
}
}
849 850 851 852 853 |
# File 'lib/framework/_socket.rb', line 849 def self.tcp_server_loop(host=nil, port, &b) # :yield: socket, client_addrinfo tcp_server_sockets(host, port) {|sockets| accept_loop(sockets, &b) } end |
.tcp_server_sockets(host = nil, port) ⇒ Object
creates TCP/IP server sockets for host and port. host is optional.
If no block given, it returns an array of listening sockets.
If a block is given, the block is called with the sockets. The value of the block is returned. The socket is closed when this method returns.
If port is 0, actual port number is chosen dynamically. However all sockets in the result has same port number.
# tcp_server_sockets returns two sockets.
sockets = Socket.tcp_server_sockets(1296)
p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>]
# The sockets contains IPv6 and IPv4 sockets.
sockets.each {|s| p s.local_address }
#=> #<Addrinfo: [::]:1296 TCP>
# #<Addrinfo: 0.0.0.0:1296 TCP>
# IPv6 and IPv4 socket has same port number, 53114, even if it is chosen dynamically.
sockets = Socket.tcp_server_sockets(0)
sockets.each {|s| p s.local_address }
#=> #<Addrinfo: [::]:53114 TCP>
# #<Addrinfo: 0.0.0.0:53114 TCP>
# The block is called with the sockets.
Socket.tcp_server_sockets(0) {|sockets|
p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>]
}
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
# File 'lib/framework/_socket.rb', line 749 def self.tcp_server_sockets(host=nil, port) if port == 0 sockets = tcp_server_sockets_port0(host) else last_error = nil sockets = [] begin Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s } if sockets.empty? raise last_error end rescue Exception sockets.each {|s| s.close } raise end end if block_given? begin yield sockets ensure sockets.each {|s| s.close if !s.closed? } end else sockets end end |
.tcp_server_sockets_port0(host) ⇒ Object
698 699 700 701 702 703 704 705 706 707 708 709 710 |
# File 'lib/framework/_socket.rb', line 698 def self.tcp_server_sockets_port0(host) ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE) sockets = ip_sockets_port0(ai_list, true) begin sockets.each {|s| s.listen(Socket::SOMAXCONN) } rescue Exception sockets.each {|s| s.close } raise end sockets end |
.udp_server_loop(host = nil, port, &b) ⇒ Object
:call-seq:
Socket.udp_server_loop(port) {|msg, msg_src| ... }
Socket.udp_server_loop(host, port) {|msg, msg_src| ... }
creates a UDP/IP server on port and calls the block for each message arrived. The block is called with the message and its source information.
This method allocates sockets internally using port. If host is specified, it is used conjunction with port to determine the server addresses.
The msg is a string.
The msg_src is a Socket::UDPSource object. It is used for reply.
# UDP/IP echo server.
Socket.udp_server_loop(9261) {|msg, msg_src|
msg_src.reply msg
}
1018 1019 1020 1021 1022 |
# File 'lib/framework/_socket.rb', line 1018 def self.udp_server_loop(host=nil, port, &b) # :yield: message, message_source udp_server_sockets(host, port) {|sockets| udp_server_loop_on(sockets, &b) } end |
.udp_server_loop_on(sockets, &b) ⇒ Object
:call-seq:
Socket.udp_server_loop_on(sockets) {|msg, msg_src| ... }
Run UDP/IP server loop on the given sockets.
The return value of Socket.udp_server_sockets is appropriate for the argument.
It calls the block for each message received.
991 992 993 994 995 996 |
# File 'lib/framework/_socket.rb', line 991 def self.udp_server_loop_on(sockets, &b) # :yield: msg, msg_src loop { readable, _, _ = IO.select(sockets) udp_server_recv(readable, &b) } end |
.udp_server_recv(sockets) ⇒ Object
:call-seq:
Socket.udp_server_recv(sockets) {|msg, msg_src| ... }
Receive UDP/IP packets from the given sockets. For each packet received, the block is called.
The block receives msg and msg_src. msg is a string which is the payload of the received packet. msg_src is a Socket::UDPSource object which is used for reply.
Socket.udp_server_loop can be implemented using this method as follows.
udp_server_sockets(host, port) {|sockets|
loop {
readable, _, _ = IO.select(sockets)
udp_server_recv(readable) {|msg, msg_src| ... }
}
}
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 |
# File 'lib/framework/_socket.rb', line 964 def self.udp_server_recv(sockets) sockets.each {|r| msg, sender_addrinfo, _, *controls = r.recvmsg_nonblock(exception: false) next if msg == :wait_readable ai = r.local_address if ai.ipv6? and pktinfo = controls.find {|c| c.cmsg_is?(:IPV6, :PKTINFO) } ai = Addrinfo.udp(pktinfo.ipv6_pktinfo_addr.ip_address, ai.ip_port) yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg| r.sendmsg reply_msg, 0, sender_addrinfo, pktinfo } else yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg| r.send reply_msg, 0, sender_addrinfo } end } end |
.udp_server_sockets(host = nil, port) ⇒ Object
:call-seq:
Socket.udp_server_sockets([host, ] port)
Creates UDP/IP sockets for a UDP server.
If no block given, it returns an array of sockets.
If a block is given, the block is called with the sockets. The value of the block is returned. The sockets are closed when this method returns.
If port is zero, some port is chosen. But the chosen port is used for the all sockets.
# UDP/IP echo server
Socket.udp_server_sockets(0) {|sockets|
p sockets.first.local_address.ip_port #=> 32963
Socket.udp_server_loop_on(sockets) {|msg, msg_src|
msg_src.reply msg
}
}
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 |
# File 'lib/framework/_socket.rb', line 877 def self.udp_server_sockets(host=nil, port) last_error = nil sockets = [] ipv6_recvpktinfo = nil if defined? Socket::AncillaryData if defined? Socket::IPV6_RECVPKTINFO # RFC 3542 ipv6_recvpktinfo = Socket::IPV6_RECVPKTINFO elsif defined? Socket::IPV6_PKTINFO # RFC 2292 ipv6_recvpktinfo = Socket::IPV6_PKTINFO end end local_addrs = Socket.ip_address_list ip_list = [] Addrinfo.foreach(host, port, nil, :DGRAM, nil, Socket::AI_PASSIVE) {|ai| if ai.ipv4? && ai.ip_address == "0.0.0.0" local_addrs.each {|a| next if !a.ipv4? ip_list << Addrinfo.new(a.to_sockaddr, :INET, :DGRAM, 0); } elsif ai.ipv6? && ai.ip_address == "::" && !ipv6_recvpktinfo local_addrs.each {|a| next if !a.ipv6? ip_list << Addrinfo.new(a.to_sockaddr, :INET6, :DGRAM, 0); } else ip_list << ai end } if port == 0 sockets = ip_sockets_port0(ip_list, false) else ip_list.each {|ip| ai = Addrinfo.udp(ip.ip_address, port) begin s = ai.bind rescue SystemCallError last_error = $! next end sockets << s } if sockets.empty? raise last_error end end sockets.each {|s| ai = s.local_address if ipv6_recvpktinfo && ai.ipv6? && ai.ip_address == "::" s.setsockopt(:IPV6, ipv6_recvpktinfo, 1) end } if block_given? begin yield sockets ensure sockets.each {|s| s.close if !s.closed? } if sockets end else sockets end end |
.unix(path) ⇒ Object
creates a new socket connected to path using UNIX socket socket.
If a block is given, the block is called with the socket. The value of the block is returned. The socket is closed when this method returns.
If no block is given, the socket is returned.
# talk to /tmp/sock socket.
Socket.unix("/tmp/sock") {|sock|
t = Thread.new { IO.copy_stream(sock, STDOUT) }
IO.copy_stream(STDIN, sock)
t.join
}
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 |
# File 'lib/framework/_socket.rb', line 1068 def self.unix(path) # :yield: socket addr = Addrinfo.unix(path) sock = addr.connect if block_given? begin yield sock ensure sock.close if !sock.closed? end else sock end end |
.unix_server_loop(path, &b) ⇒ Object
creates a UNIX socket server on path. It calls the block for each socket accepted.
If host is specified, it is used with port to determine the server ports.
The socket is not closed when the block returns. So application should close it.
This method deletes the socket file pointed by path at first if the file is a socket file and it is owned by the user of the application. This is safe only if the directory of path is not changed by a malicious user. So don’t use /tmp/malicious-users-directory/socket. Note that /tmp/socket and /tmp/your-private-directory/socket is safe assuming that /tmp has sticky bit.
# Sequential echo server.
# It services only one client at a time.
Socket.unix_server_loop("/tmp/sock") {|sock, client_addrinfo|
begin
IO.copy_stream(sock, sock)
ensure
sock.close
end
}
1155 1156 1157 1158 1159 |
# File 'lib/framework/_socket.rb', line 1155 def self.unix_server_loop(path, &b) # :yield: socket, client_addrinfo unix_server_socket(path) {|serv| accept_loop(serv, &b) } end |
.unix_server_socket(path) ⇒ Object
creates a UNIX server socket on path
If no block given, it returns a listening socket.
If a block is given, it is called with the socket and the block value is returned. When the block exits, the socket is closed and the socket file is removed.
socket = Socket.unix_server_socket("/tmp/s")
p socket #=> #<Socket:fd 3>
p socket.local_address #=> #<Addrinfo: /tmp/s SOCK_STREAM>
Socket.unix_server_socket("/tmp/sock") {|s|
p s #=> #<Socket:fd 3>
p s.local_address #=> # #<Addrinfo: /tmp/sock SOCK_STREAM>
}
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
# File 'lib/framework/_socket.rb', line 1098 def self.unix_server_socket(path) if !unix_socket_abstract_name?(path) begin st = File.lstat(path) rescue Errno::ENOENT end if st&.socket? && st.owned? File.unlink path end end s = Addrinfo.unix(path).listen if block_given? begin yield s ensure s.close if !s.closed? if !unix_socket_abstract_name?(path) File.unlink path end end else s end end |
.unpack_sockaddr_in(req) ⇒ Object
335 336 |
# File 'lib/framework/autocomplete/Socket.rb', line 335 def self.unpack_sockaddr_in(req) end |
Instance Method Details
#accept ⇒ Object
345 346 |
# File 'lib/framework/autocomplete/Socket.rb', line 345 def accept end |
#accept_nonblock ⇒ Object
call-seq:
socket.accept_nonblock([]) => [client_socket, client_addrinfo]
Accepts an incoming connection using accept(2) after O_NONBLOCK is set for the underlying file descriptor. It returns an array containing the accepted socket for the incoming connection, client_socket, and an Addrinfo, client_addrinfo.
Example
# In one script, start this first
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.bind(sockaddr)
socket.listen(5)
begin # emulate blocking accept
client_socket, client_addrinfo = socket.accept_nonblock
rescue IO::WaitReadable, Errno::EINTR
IO.select([socket])
retry
end
puts "The client said, '#{client_socket.readline.chomp}'"
client_socket.puts "Hello from script one!"
socket.close
# In another script, start this second
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.connect(sockaddr)
socket.puts "Hello from script 2."
puts "The server said, '#{socket.readline.chomp}'"
socket.close
Refer to Socket#accept for the exceptions that may be thrown if the call to accept_nonblock fails.
Socket#accept_nonblock may raise any error corresponding to accept(2) failure, including Errno::EWOULDBLOCK.
If the exception is Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED or Errno::EPROTO, it is extended by IO::WaitReadable. So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
By specifying ‘exception: false`, the options hash allows you to indicate that accept_nonblock should not raise an IO::WaitReadable exception, but return the symbol :wait_readable instead.
See
-
Socket#accept
581 582 583 |
# File 'lib/framework/_socket.rb', line 581 def accept_nonblock(exception: true) __accept_nonblock(exception) end |
#bind(req) ⇒ Object
341 342 |
# File 'lib/framework/autocomplete/Socket.rb', line 341 def bind(req) end |
#connect(req) ⇒ Object
337 338 |
# File 'lib/framework/autocomplete/Socket.rb', line 337 def connect(req) end |
#connect_nonblock(req) ⇒ Object
call-seq:
socket.connect_nonblock(remote_sockaddr, []) => 0
Requests a connection to be made on the given remote_sockaddr after O_NONBLOCK is set for the underlying file descriptor. Returns 0 if successful, otherwise an exception is raised.
Parameter
# +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
Example:
# Pull down Google's web page
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, 'www.google.com')
begin # emulate blocking connect
socket.connect_nonblock(sockaddr)
rescue IO::WaitWritable
IO.select(nil, [socket]) # wait 3-way handshake completion
begin
socket.connect_nonblock(sockaddr) # check connection failure
rescue Errno::EISCONN
end
end
socket.write("GET / HTTP/1.0\r\n\r\n")
results = socket.read
Refer to Socket#connect for the exceptions that may be thrown if the call to connect_nonblock fails.
Socket#connect_nonblock may raise any error corresponding to connect(2) failure, including Errno::EINPROGRESS.
If the exception is Errno::EINPROGRESS, it is extended by IO::WaitWritable. So IO::WaitWritable can be used to rescue the exceptions for retrying connect_nonblock.
By specifying ‘exception: false`, the options hash allows you to indicate that connect_nonblock should not raise an IO::WaitWritable exception, but return the symbol :wait_writable instead.
See
# Socket#connect
1205 1206 1207 |
# File 'lib/framework/_socket.rb', line 1205 def connect_nonblock(addr, exception: true) __connect_nonblock(addr, exception) end |
#ipv6only! ⇒ Object
enable the socket option IPV6_V6ONLY if IPV6_V6ONLY is available.
452 453 454 455 456 |
# File 'lib/framework/_socket.rb', line 452 def ipv6only! if defined? Socket::IPV6_V6ONLY self.setsockopt(:IPV6, :V6ONLY, 1) end end |
#listen(req) ⇒ Object
343 344 |
# File 'lib/framework/autocomplete/Socket.rb', line 343 def listen(req) end |
#recvfrom(rest) ⇒ Object
351 352 |
# File 'lib/framework/autocomplete/Socket.rb', line 351 def recvfrom(rest) end |
#recvfrom_nonblock(rest) ⇒ Object
call-seq:
socket.recvfrom_nonblock(maxlen[, flags[, outbuf[, opts]]]) => [mesg, sender_addrinfo]
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 first element of the results, mesg, is the data received. The second element, sender_addrinfo, contains protocol-specific address information of the sender.
When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns an empty string as data. The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
Parameters
-
maxlen- the maximum number of bytes to receive from the socket -
flags- zero or more of theMSG_options -
outbuf- destination String buffer -
opts- keyword hash, supporting ‘exception: false`
Example
# In one file, start this first
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.bind(sockaddr)
socket.listen(5)
client, client_addrinfo = socket.accept
begin # emulate blocking recvfrom
pair = client.recvfrom_nonblock(20)
rescue IO::WaitReadable
IO.select([client])
retry
end
data = pair[0].chomp
puts "I only received 20 bytes '#{data}'"
sleep 1
socket.close
# In another file, start this second
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(2200, 'localhost')
socket.connect(sockaddr)
socket.puts "Watch this get cut short!"
socket.close
Refer to Socket#recvfrom for the exceptions that may be thrown if the call to recvfrom_nonblock fails.
Socket#recvfrom_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 recvfrom_nonblock.
By specifying ‘exception: false`, the options hash allows you to indicate that accept_nonblock should not raise an IO::WaitReadable exception, but return the symbol :wait_readable instead.
See
-
Socket#recvfrom
524 525 526 |
# File 'lib/framework/_socket.rb', line 524 def recvfrom_nonblock(len, flag = 0, str = nil, exception: true) __recvfrom_nonblock(len, flag, str, exception) end |
#sysaccept ⇒ Object
349 350 |
# File 'lib/framework/autocomplete/Socket.rb', line 349 def sysaccept end |