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 * Internally, TCPServer.new calls getaddrinfo() function to 00027 * obtain addresses. 00028 * If getaddrinfo() returns multiple addresses, 00029 * TCPServer.new tries to create a server socket for each address 00030 * and returns first one that is successful. 00031 * 00032 */ 00033 static VALUE 00034 tcp_svr_init(int argc, VALUE *argv, VALUE sock) 00035 { 00036 VALUE hostname, port; 00037 00038 rb_scan_args(argc, argv, "011", &hostname, &port); 00039 return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER); 00040 } 00041 00042 /* 00043 * call-seq: 00044 * tcpserver.accept => tcpsocket 00045 * 00046 * Accepts an incoming connection. It returns a new TCPSocket object. 00047 * 00048 * TCPServer.open("127.0.0.1", 14641) {|serv| 00049 * s = serv.accept 00050 * s.puts Time.now 00051 * s.close 00052 * } 00053 * 00054 */ 00055 static VALUE 00056 tcp_accept(VALUE sock) 00057 { 00058 rb_io_t *fptr; 00059 union_sockaddr from; 00060 socklen_t fromlen; 00061 00062 GetOpenFile(sock, fptr); 00063 fromlen = (socklen_t)sizeof(from); 00064 return rsock_s_accept(rb_cTCPSocket, fptr->fd, &from.addr, &fromlen); 00065 } 00066 00067 /* 00068 * call-seq: 00069 * tcpserver.accept_nonblock => tcpsocket 00070 * 00071 * Accepts an incoming connection using accept(2) after 00072 * O_NONBLOCK is set for the underlying file descriptor. 00073 * It returns an accepted TCPSocket for the incoming connection. 00074 * 00075 * === Example 00076 * require 'socket' 00077 * serv = TCPServer.new(2202) 00078 * begin # emulate blocking accept 00079 * sock = serv.accept_nonblock 00080 * rescue IO::WaitReadable, Errno::EINTR 00081 * IO.select([serv]) 00082 * retry 00083 * end 00084 * # sock is an accepted socket. 00085 * 00086 * Refer to Socket#accept for the exceptions that may be thrown if the call 00087 * to TCPServer#accept_nonblock fails. 00088 * 00089 * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure, 00090 * including Errno::EWOULDBLOCK. 00091 * 00092 * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED, Errno::EPROTO, 00093 * it is extended by IO::WaitReadable. 00094 * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock. 00095 * 00096 * === See 00097 * * TCPServer#accept 00098 * * Socket#accept 00099 */ 00100 static VALUE 00101 tcp_accept_nonblock(VALUE sock) 00102 { 00103 rb_io_t *fptr; 00104 union_sockaddr from; 00105 socklen_t fromlen; 00106 00107 GetOpenFile(sock, fptr); 00108 fromlen = (socklen_t)sizeof(from); 00109 return rsock_s_accept_nonblock(rb_cTCPSocket, fptr, &from.addr, &fromlen); 00110 } 00111 00112 /* 00113 * call-seq: 00114 * tcpserver.sysaccept => file_descriptor 00115 * 00116 * Returns a file descriptor of a accepted connection. 00117 * 00118 * TCPServer.open("127.0.0.1", 28561) {|serv| 00119 * fd = serv.sysaccept 00120 * s = IO.for_fd(fd) 00121 * s.puts Time.now 00122 * s.close 00123 * } 00124 * 00125 */ 00126 static VALUE 00127 tcp_sysaccept(VALUE sock) 00128 { 00129 rb_io_t *fptr; 00130 union_sockaddr from; 00131 socklen_t fromlen; 00132 00133 GetOpenFile(sock, fptr); 00134 fromlen = (socklen_t)sizeof(from); 00135 return rsock_s_accept(0, fptr->fd, &from.addr, &fromlen); 00136 } 00137 00138 void 00139 rsock_init_tcpserver(void) 00140 { 00141 /* 00142 * Document-class: TCPServer < TCPSocket 00143 * 00144 * TCPServer represents a TCP/IP server socket. 00145 * 00146 * A simple TCP server may look like: 00147 * 00148 * require 'socket' 00149 * 00150 * server = TCPServer.new 2000 # Server bind to port 2000 00151 * loop do 00152 * client = server.accept # Wait for a client to connect 00153 * client.puts "Hello !" 00154 * client.puts "Time is #{Time.now}" 00155 * client.close 00156 * end 00157 * 00158 * A more usable server (serving multiple clients): 00159 * 00160 * require 'socket' 00161 * 00162 * server = TCPServer.new 2000 00163 * loop do 00164 * Thread.start(server.accept) do |client| 00165 * client.puts "Hello !" 00166 * client.puts "Time is #{Time.now}" 00167 * client.close 00168 * end 00169 * end 00170 * 00171 */ 00172 rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket); 00173 rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0); 00174 rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0); 00175 rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0); 00176 rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1); 00177 rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */ 00178 } 00179
1.6.1