Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 tcpserver.c - 00004 00005 created at: Thu Mar 31 12:21:29 JST 1994 00006 00007 Copyright (C) 1993-2007 Yukihiro Matsumoto 00008 00009 ************************************************/ 00010 00011 #include "rubysocket.h" 00012 00013 /* 00014 * call-seq: 00015 * TCPServer.new([hostname,] port) => tcpserver 00016 * 00017 * Creates a new server socket bound to _port_. 00018 * 00019 * If _hostname_ is given, the socket is bound to it. 00020 * 00021 * serv = TCPServer.new("127.0.0.1", 28561) 00022 * s = serv.accept 00023 * s.puts Time.now 00024 * s.close 00025 */ 00026 static VALUE 00027 tcp_svr_init(int argc, VALUE *argv, VALUE sock) 00028 { 00029 VALUE hostname, port; 00030 00031 rb_scan_args(argc, argv, "011", &hostname, &port); 00032 return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER); 00033 } 00034 00035 /* 00036 * call-seq: 00037 * tcpserver.accept => tcpsocket 00038 * 00039 * TCPServer.open("127.0.0.1", 14641) {|serv| 00040 * s = serv.accept 00041 * s.puts Time.now 00042 * s.close 00043 * } 00044 * 00045 */ 00046 static VALUE 00047 tcp_accept(VALUE sock) 00048 { 00049 rb_io_t *fptr; 00050 struct sockaddr_storage from; 00051 socklen_t fromlen; 00052 00053 GetOpenFile(sock, fptr); 00054 fromlen = (socklen_t)sizeof(from); 00055 return rsock_s_accept(rb_cTCPSocket, fptr->fd, 00056 (struct sockaddr*)&from, &fromlen); 00057 } 00058 00059 /* 00060 * call-seq: 00061 * tcpserver.accept_nonblock => tcpsocket 00062 * 00063 * Accepts an incoming connection using accept(2) after 00064 * O_NONBLOCK is set for the underlying file descriptor. 00065 * It returns an accepted TCPSocket for the incoming connection. 00066 * 00067 * === Example 00068 * require 'socket' 00069 * serv = TCPServer.new(2202) 00070 * begin # emulate blocking accept 00071 * sock = serv.accept_nonblock 00072 * rescue IO::WaitReadable, Errno::EINTR 00073 * IO.select([serv]) 00074 * retry 00075 * end 00076 * # sock is an accepted socket. 00077 * 00078 * Refer to Socket#accept for the exceptions that may be thrown if the call 00079 * to TCPServer#accept_nonblock fails. 00080 * 00081 * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure, 00082 * including Errno::EWOULDBLOCK. 00083 * 00084 * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED, Errno::EPROTO, 00085 * it is extended by IO::WaitReadable. 00086 * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock. 00087 * 00088 * === See 00089 * * TCPServer#accept 00090 * * Socket#accept 00091 */ 00092 static VALUE 00093 tcp_accept_nonblock(VALUE sock) 00094 { 00095 rb_io_t *fptr; 00096 struct sockaddr_storage from; 00097 socklen_t fromlen; 00098 00099 GetOpenFile(sock, fptr); 00100 fromlen = (socklen_t)sizeof(from); 00101 return rsock_s_accept_nonblock(rb_cTCPSocket, fptr, 00102 (struct sockaddr *)&from, &fromlen); 00103 } 00104 00105 /* 00106 * call-seq: 00107 * tcpserver.sysaccept => file_descriptor 00108 * 00109 * Returns a file descriptor of a accepted connection. 00110 * 00111 * TCPServer.open("127.0.0.1", 28561) {|serv| 00112 * fd = serv.sysaccept 00113 * s = IO.for_fd(fd) 00114 * s.puts Time.now 00115 * s.close 00116 * } 00117 * 00118 */ 00119 static VALUE 00120 tcp_sysaccept(VALUE sock) 00121 { 00122 rb_io_t *fptr; 00123 struct sockaddr_storage from; 00124 socklen_t fromlen; 00125 00126 GetOpenFile(sock, fptr); 00127 fromlen = (socklen_t)sizeof(from); 00128 return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); 00129 } 00130 00131 void 00132 rsock_init_tcpserver(void) 00133 { 00134 /* 00135 * Document-class: TCPServer < TCPSocket 00136 * 00137 * TCPServer represents a TCP/IP server socket. 00138 * 00139 * A simple TCP server may look like: 00140 * 00141 * require 'socket' 00142 * 00143 * server = TCPServer.new 2000 # Server bind to port 2000 00144 * loop do 00145 * client = server.accept # Wait for a client to connect 00146 * client.puts "Hello !" 00147 * client.puts "Time is #{Time.now}" 00148 * client.close 00149 * end 00150 * 00151 * A more usable server (serving multiple clients): 00152 * 00153 * require 'socket' 00154 * 00155 * server = TCPServer.new 2000 00156 * loop do 00157 * Thread.start(server.accept) do |client| 00158 * client.puts "Hello !" 00159 * client.puts "Time is #{Time.now}" 00160 * client.close 00161 * end 00162 * end 00163 * 00164 */ 00165 rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket); 00166 rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0); 00167 rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0); 00168 rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0); 00169 rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1); 00170 rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */ 00171 } 00172