Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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
27 tcp_svr_init(int argc, VALUE *argv, VALUE sock)
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
47 tcp_accept(VALUE sock)
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
93 tcp_accept_nonblock(VALUE sock)
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);
101 return rsock_s_accept_nonblock(rb_cTCPSocket, fptr,
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
120 tcp_sysaccept(VALUE sock)
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
132 rsock_init_tcpserver(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 */
165 rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
166 rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
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 }
172