Ruby  2.1.10p492(2016-04-01revision54464)
tcpserver.c
Go to the documentation of this file.
1 /************************************************
2 
3  tcpserver.c -
4 
5  created at: Thu Mar 31 12:21:29 JST 1994
6 
7  Copyright (C) 1993-2007 Yukihiro Matsumoto
8 
9 ************************************************/
10 
11 #include "rubysocket.h"
12 
13 /*
14  * call-seq:
15  * TCPServer.new([hostname,] port) => tcpserver
16  *
17  * Creates a new server socket bound to _port_.
18  *
19  * If _hostname_ is given, the socket is bound to it.
20  *
21  * serv = TCPServer.new("127.0.0.1", 28561)
22  * s = serv.accept
23  * s.puts Time.now
24  * s.close
25  *
26  * Internally, TCPServer.new calls getaddrinfo() function to
27  * obtain addresses.
28  * If getaddrinfo() returns multiple addresses,
29  * TCPServer.new tries to create a server socket for each address
30  * and returns first one that is successful.
31  *
32  */
33 static VALUE
35 {
36  VALUE hostname, port;
37 
38  rb_scan_args(argc, argv, "011", &hostname, &port);
39  return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER);
40 }
41 
42 /*
43  * call-seq:
44  * tcpserver.accept => tcpsocket
45  *
46  * Accepts an incoming connection. It returns a new TCPSocket object.
47  *
48  * TCPServer.open("127.0.0.1", 14641) {|serv|
49  * s = serv.accept
50  * s.puts Time.now
51  * s.close
52  * }
53  *
54  */
55 static VALUE
57 {
58  rb_io_t *fptr;
59  union_sockaddr from;
60  socklen_t fromlen;
61 
62  GetOpenFile(sock, fptr);
63  fromlen = (socklen_t)sizeof(from);
64  return rsock_s_accept(rb_cTCPSocket, fptr->fd, &from.addr, &fromlen);
65 }
66 
67 /*
68  * call-seq:
69  * tcpserver.accept_nonblock => tcpsocket
70  *
71  * Accepts an incoming connection using accept(2) after
72  * O_NONBLOCK is set for the underlying file descriptor.
73  * It returns an accepted TCPSocket for the incoming connection.
74  *
75  * === Example
76  * require 'socket'
77  * serv = TCPServer.new(2202)
78  * begin # emulate blocking accept
79  * sock = serv.accept_nonblock
80  * rescue IO::WaitReadable, Errno::EINTR
81  * IO.select([serv])
82  * retry
83  * end
84  * # sock is an accepted socket.
85  *
86  * Refer to Socket#accept for the exceptions that may be thrown if the call
87  * to TCPServer#accept_nonblock fails.
88  *
89  * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
90  * including Errno::EWOULDBLOCK.
91  *
92  * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED, Errno::EPROTO,
93  * it is extended by IO::WaitReadable.
94  * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
95  *
96  * === See
97  * * TCPServer#accept
98  * * Socket#accept
99  */
100 static VALUE
102 {
103  rb_io_t *fptr;
104  union_sockaddr from;
105  socklen_t fromlen;
106 
107  GetOpenFile(sock, fptr);
108  fromlen = (socklen_t)sizeof(from);
109  return rsock_s_accept_nonblock(rb_cTCPSocket, fptr, &from.addr, &fromlen);
110 }
111 
112 /*
113  * call-seq:
114  * tcpserver.sysaccept => file_descriptor
115  *
116  * Returns a file descriptor of a accepted connection.
117  *
118  * TCPServer.open("127.0.0.1", 28561) {|serv|
119  * fd = serv.sysaccept
120  * s = IO.for_fd(fd)
121  * s.puts Time.now
122  * s.close
123  * }
124  *
125  */
126 static VALUE
128 {
129  rb_io_t *fptr;
130  union_sockaddr from;
131  socklen_t fromlen;
132 
133  GetOpenFile(sock, fptr);
134  fromlen = (socklen_t)sizeof(from);
135  return rsock_s_accept(0, fptr->fd, &from.addr, &fromlen);
136 }
137 
138 void
140 {
141  /*
142  * Document-class: TCPServer < TCPSocket
143  *
144  * TCPServer represents a TCP/IP server socket.
145  *
146  * A simple TCP server may look like:
147  *
148  * require 'socket'
149  *
150  * server = TCPServer.new 2000 # Server bind to port 2000
151  * loop do
152  * client = server.accept # Wait for a client to connect
153  * client.puts "Hello !"
154  * client.puts "Time is #{Time.now}"
155  * client.close
156  * end
157  *
158  * A more usable server (serving multiple clients):
159  *
160  * require 'socket'
161  *
162  * server = TCPServer.new 2000
163  * loop do
164  * Thread.start(server.accept) do |client|
165  * client.puts "Hello !"
166  * client.puts "Time is #{Time.now}"
167  * client.close
168  * end
169  * end
170  *
171  */
174  rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
175  rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
176  rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
177  rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
178 }
static VALUE tcp_svr_init(int argc, VALUE *argv, VALUE sock)
Definition: tcpserver.c:34
static VALUE tcp_accept(VALUE sock)
Definition: tcpserver.c:56
VALUE rsock_sock_listen(VALUE sock, VALUE log)
Definition: socket.c:649
Definition: io.h:61
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:574
#define GetOpenFile(obj, fp)
Definition: io.h:118
VALUE rb_cTCPSocket
Definition: init.c:15
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:611
int fd
Definition: io.h:62
int argc
Definition: ruby.c:131
void rsock_init_tcpserver(void)
Definition: tcpserver.c:139
int socklen_t
Definition: getaddrinfo.c:84
#define INET_SERVER
Definition: rubysocket.h:225
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
#define Qnil
Definition: ruby.h:427
VALUE rb_cTCPServer
Definition: init.c:16
unsigned long VALUE
Definition: ruby.h:88
static VALUE tcp_accept_nonblock(VALUE sock)
Definition: tcpserver.c:101
static VALUE tcp_sysaccept(VALUE sock)
Definition: tcpserver.c:127
VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:534
VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type)
Definition: ipsocket.c:149
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
char ** argv
Definition: ruby.c:132
struct sockaddr addr
Definition: rubysocket.h:185