Ruby  3.1.0dev(2021-09-10revisionb76ad15ed0da636161de0243c547ee1e6fc95681)
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
34 tcp_svr_init(int argc, VALUE *argv, VALUE sock)
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, Qnil, Qnil);
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
56 tcp_accept(VALUE server)
57 {
58  union_sockaddr buffer;
59  socklen_t length = sizeof(buffer);
60 
61  return rsock_s_accept(rb_cTCPSocket, server, &buffer.addr, &length);
62 }
63 
64 /* :nodoc: */
65 static VALUE
66 tcp_accept_nonblock(VALUE sock, VALUE ex)
67 {
68  rb_io_t *fptr;
69  union_sockaddr from;
70  socklen_t len = (socklen_t)sizeof(from);
71 
72  GetOpenFile(sock, fptr);
73  return rsock_s_accept_nonblock(rb_cTCPSocket, ex, fptr, &from.addr, &len);
74 }
75 
76 /*
77  * call-seq:
78  * tcpserver.sysaccept => file_descriptor
79  *
80  * Returns a file descriptor of a accepted connection.
81  *
82  * TCPServer.open("127.0.0.1", 28561) {|serv|
83  * fd = serv.sysaccept
84  * s = IO.for_fd(fd)
85  * s.puts Time.now
86  * s.close
87  * }
88  *
89  */
90 static VALUE
91 tcp_sysaccept(VALUE server)
92 {
93  union_sockaddr buffer;
94  socklen_t length = sizeof(buffer);
95 
96  return rsock_s_accept(0, server, &buffer.addr, &length);
97 }
98 
99 void
101 {
102  /*
103  * Document-class: TCPServer < TCPSocket
104  *
105  * TCPServer represents a TCP/IP server socket.
106  *
107  * A simple TCP server may look like:
108  *
109  * require 'socket'
110  *
111  * server = TCPServer.new 2000 # Server bind to port 2000
112  * loop do
113  * client = server.accept # Wait for a client to connect
114  * client.puts "Hello !"
115  * client.puts "Time is #{Time.now}"
116  * client.close
117  * end
118  *
119  * A more usable server (serving multiple clients):
120  *
121  * require 'socket'
122  *
123  * server = TCPServer.new 2000
124  * loop do
125  * Thread.start(server.accept) do |client|
126  * client.puts "Hello !"
127  * client.puts "Time is #{Time.now}"
128  * client.close
129  * end
130  * end
131  *
132  */
134  rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
136  "__accept_nonblock", tcp_accept_nonblock, 1);
137  rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
138  rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
139  rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
140 }
rb_cTCPServer
VALUE rb_cTCPServer
Definition: init.c:20
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:759
union_sockaddr
Definition: rubysocket.h:218
GetOpenFile
#define GetOpenFile
Definition: io.h:125
rsock_s_accept_nonblock
VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:636
argv
char ** argv
Definition: ruby.c:243
socklen_t
int socklen_t
Definition: getaddrinfo.c:83
rsock_s_accept
VALUE rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len)
Definition: init.c:678
rsock_init_tcpserver
void rsock_init_tcpserver(void)
Definition: tcpserver.c:100
len
uint8_t len
Definition: escape.c:17
rsock_init_inetsock
VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout)
Definition: ipsocket.c:171
Qnil
#define Qnil
Definition: special_consts.h:51
rb_define_private_method
#define rb_define_private_method(klass, mid, func, arity)
Defines klass#mid and makes it private.
Definition: cxxanyargs.hpp:662
INET_SERVER
#define INET_SERVER
Definition: rubysocket.h:254
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2347
VALUE
unsigned long VALUE
Definition: value.h:38
argc
int argc
Definition: ruby.c:242
rsock_sock_listen
VALUE rsock_sock_listen(VALUE sock, VALUE log)
Definition: socket.c:607
rubysocket.h
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:655
rb_cTCPSocket
VALUE rb_cTCPSocket
Definition: init.c:19
rb_io_t
Definition: io.h:61
union_sockaddr::addr
struct sockaddr addr
Definition: rubysocket.h:219