Ruby: ext/socket/tcpserver.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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