Ruby  2.0.0p598(2014-11-13revision48408)
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 static VALUE
28 {
29  VALUE hostname, port;
30 
31  rb_scan_args(argc, argv, "011", &hostname, &port);
32  return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER);
33 }
34 
35 /*
36  * call-seq:
37  * tcpserver.accept => tcpsocket
38  *
39  * TCPServer.open("127.0.0.1", 14641) {|serv|
40  * s = serv.accept
41  * s.puts Time.now
42  * s.close
43  * }
44  *
45  */
46 static VALUE
48 {
49  rb_io_t *fptr;
50  struct sockaddr_storage from;
51  socklen_t fromlen;
52 
53  GetOpenFile(sock, fptr);
54  fromlen = (socklen_t)sizeof(from);
55  return rsock_s_accept(rb_cTCPSocket, fptr->fd,
56  (struct sockaddr*)&from, &fromlen);
57 }
58 
59 /*
60  * call-seq:
61  * tcpserver.accept_nonblock => tcpsocket
62  *
63  * Accepts an incoming connection using accept(2) after
64  * O_NONBLOCK is set for the underlying file descriptor.
65  * It returns an accepted TCPSocket for the incoming connection.
66  *
67  * === Example
68  * require 'socket'
69  * serv = TCPServer.new(2202)
70  * begin # emulate blocking accept
71  * sock = serv.accept_nonblock
72  * rescue IO::WaitReadable, Errno::EINTR
73  * IO.select([serv])
74  * retry
75  * end
76  * # sock is an accepted socket.
77  *
78  * Refer to Socket#accept for the exceptions that may be thrown if the call
79  * to TCPServer#accept_nonblock fails.
80  *
81  * TCPServer#accept_nonblock may raise any error corresponding to accept(2) failure,
82  * including Errno::EWOULDBLOCK.
83  *
84  * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED, Errno::EPROTO,
85  * it is extended by IO::WaitReadable.
86  * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock.
87  *
88  * === See
89  * * TCPServer#accept
90  * * Socket#accept
91  */
92 static VALUE
94 {
95  rb_io_t *fptr;
96  struct sockaddr_storage from;
97  socklen_t fromlen;
98 
99  GetOpenFile(sock, fptr);
100  fromlen = (socklen_t)sizeof(from);
102  (struct sockaddr *)&from, &fromlen);
103 }
104 
105 /*
106  * call-seq:
107  * tcpserver.sysaccept => file_descriptor
108  *
109  * Returns a file descriptor of a accepted connection.
110  *
111  * TCPServer.open("127.0.0.1", 28561) {|serv|
112  * fd = serv.sysaccept
113  * s = IO.for_fd(fd)
114  * s.puts Time.now
115  * s.close
116  * }
117  *
118  */
119 static VALUE
121 {
122  rb_io_t *fptr;
123  struct sockaddr_storage from;
124  socklen_t fromlen;
125 
126  GetOpenFile(sock, fptr);
127  fromlen = (socklen_t)sizeof(from);
128  return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen);
129 }
130 
131 void
133 {
134  /*
135  * Document-class: TCPServer < TCPSocket
136  *
137  * TCPServer represents a TCP/IP server socket.
138  *
139  * A simple TCP server may look like:
140  *
141  * require 'socket'
142  *
143  * server = TCPServer.new 2000 # Server bind to port 2000
144  * loop do
145  * client = server.accept # Wait for a client to connect
146  * client.puts "Hello !"
147  * client.puts "Time is #{Time.now}"
148  * client.close
149  * end
150  *
151  * A more usable server (serving multiple clients):
152  *
153  * require 'socket'
154  *
155  * server = TCPServer.new 2000
156  * loop do
157  * Thread.start(server.accept) do |client|
158  * client.puts "Hello !"
159  * client.puts "Time is #{Time.now}"
160  * client.close
161  * end
162  * end
163  *
164  */
167  rb_define_method(rb_cTCPServer, "accept_nonblock", tcp_accept_nonblock, 0);
168  rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
169  rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
170  rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
171 }
static VALUE tcp_svr_init(int argc, VALUE *argv, VALUE sock)
Definition: tcpserver.c:27
static VALUE tcp_accept(VALUE sock)
Definition: tcpserver.c:47
VALUE rsock_sock_listen(VALUE sock, VALUE log)
Definition: socket.c:546
Definition: io.h:63
void rsock_init_tcpserver(void)
Definition: tcpserver.c:132
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:562
#define GetOpenFile(obj, fp)
Definition: io.h:120
VALUE rb_cTCPSocket
Definition: init.c:15
#define Qnil
Definition: tcltklib.c:1895
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:503
int fd
Definition: io.h:64
VALUE * argv
Definition: tcltklib.c:1970
#define INET_SERVER
Definition: rubysocket.h:172
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1574
VALUE rb_cTCPServer
Definition: init.c:16
int argc
Definition: tcltklib.c:1969
static VALUE tcp_accept_nonblock(VALUE sock)
Definition: tcpserver.c:93
static VALUE tcp_sysaccept(VALUE sock)
Definition: tcpserver.c:120
VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:522
VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type)
Definition: ipsocket.c:120
unsigned long VALUE
Definition: ripper.y:104
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1348