Skip to content

Commit ded8bb4

Browse files
committed
Clarify and clean up the separation between BaseServer and TCPServer
1 parent 46006a1 commit ded8bb4

File tree

3 files changed

+84
-62
lines changed

3 files changed

+84
-62
lines changed

Doc/library/socketserver.rst

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,55 @@ There are four basic concrete server classes:
2424
:meth:`~BaseServer.server_activate`. The other parameters are passed to
2525
the :class:`BaseServer` base class.
2626

27+
In addition to the methods and attributes inherited from :class:`BaseServer`,
28+
:class:`TCPServer` provides:
29+
30+
31+
.. method:: fileno()
32+
33+
Return an integer file descriptor for the socket on which the server is
34+
listening. This function is most commonly passed to :mod:`selectors`, to
35+
allow monitoring multiple servers in the same process.
36+
37+
38+
.. method:: server_bind()
39+
40+
Called by the server's constructor to bind the socket to the desired address.
41+
May be overridden.
42+
43+
44+
.. attribute:: address_family
45+
46+
The family of protocols to which the server's socket belongs.
47+
Common examples are :const:`socket.AF_INET` and :const:`socket.AF_UNIX`.
48+
49+
50+
.. attribute:: socket
51+
52+
The socket object on which the server will listen for incoming requests.
53+
54+
55+
.. attribute:: allow_reuse_address
56+
57+
Whether the server will allow the reuse of an address. This defaults to
58+
:const:`False`, and can be set in subclasses to change the policy.
59+
60+
61+
.. attribute:: request_queue_size
62+
63+
The size of the request queue. If it takes a long time to process a single
64+
request, any requests that arrive while the server is busy are placed into a
65+
queue, up to :attr:`request_queue_size` requests. Once the queue is full,
66+
further requests from clients will get a "Connection denied" error. The default
67+
value is usually 5, but this can be overridden by subclasses.
68+
69+
70+
.. attribute:: socket_type
71+
72+
The type of socket used by the server; :const:`socket.SOCK_STREAM` and
73+
:const:`socket.SOCK_DGRAM` are two common values.
74+
75+
2776

2877
.. class:: UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
2978

@@ -211,13 +260,6 @@ Server Objects
211260
:attr:`server_address` and :attr:`RequestHandlerClass` attributes.
212261

213262

214-
.. method:: fileno()
215-
216-
Return an integer file descriptor for the socket on which the server is
217-
listening. This function is most commonly passed to :mod:`selectors`, to
218-
allow monitoring multiple servers in the same process.
219-
220-
221263
.. method:: handle_request()
222264

223265
Process a single request. This function calls the following methods in
@@ -264,12 +306,6 @@ Server Objects
264306
Clean up the server. May be overridden.
265307

266308

267-
.. attribute:: address_family
268-
269-
The family of protocols to which the server's socket belongs.
270-
Common examples are :const:`socket.AF_INET` and :const:`socket.AF_UNIX`.
271-
272-
273309
.. attribute:: RequestHandlerClass
274310

275311
The user-provided request handler class; an instance of this class is created
@@ -285,36 +321,10 @@ Server Objects
285321
the address, and an integer port number: ``('127.0.0.1', 80)``, for example.
286322

287323

288-
.. attribute:: socket
289-
290-
The socket object on which the server will listen for incoming requests.
291-
292-
293324
The server classes support the following class variables:
294325

295326
.. XXX should class variables be covered before instance variables, or vice versa?
296327
297-
.. attribute:: allow_reuse_address
298-
299-
Whether the server will allow the reuse of an address. This defaults to
300-
:const:`False`, and can be set in subclasses to change the policy.
301-
302-
303-
.. attribute:: request_queue_size
304-
305-
The size of the request queue. If it takes a long time to process a single
306-
request, any requests that arrive while the server is busy are placed into a
307-
queue, up to :attr:`request_queue_size` requests. Once the queue is full,
308-
further requests from clients will get a "Connection denied" error. The default
309-
value is usually 5, but this can be overridden by subclasses.
310-
311-
312-
.. attribute:: socket_type
313-
314-
The type of socket used by the server; :const:`socket.SOCK_STREAM` and
315-
:const:`socket.SOCK_DGRAM` are two common values.
316-
317-
318328
.. attribute:: timeout
319329

320330
Timeout duration, measured in seconds, or :const:`None` if no timeout is
@@ -341,6 +351,10 @@ Server Objects
341351
socket object to be used to communicate with the client, and the client's
342352
address.
343353

354+
An implementation of :meth:`get_request` is provided by :class:`TCPServer`.
355+
Other classes which inherit from :class:`BaseServer` directly must provide
356+
their own implementation.
357+
344358

345359
.. method:: handle_error(request, client_address)
346360

@@ -382,12 +396,6 @@ Server Objects
382396
on the server's socket. May be overridden.
383397

384398

385-
.. method:: server_bind()
386-
387-
Called by the server's constructor to bind the socket to the desired address.
388-
May be overridden.
389-
390-
391399
.. method:: verify_request(request, client_address)
392400

393401
Must return a Boolean value; if the value is :const:`True`, the request will
@@ -697,4 +705,3 @@ The output of the example should look something like this:
697705
The :class:`ForkingMixIn` class is used in the same way, except that the server
698706
will spawn a new process for each request.
699707
Available only on POSIX platforms that support :func:`~os.fork`.
700-

Lib/socketserver.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,15 @@ class BaseServer:
161161
- __init__(server_address, RequestHandlerClass)
162162
- serve_forever(poll_interval=0.5)
163163
- shutdown()
164-
- handle_request() # if you do not use serve_forever()
165-
- fileno() -> int # for selector
164+
- handle_request() # if you don't use serve_forever()
165+
166+
Methods that must be overridden:
167+
168+
- get_request() -> request, client_address
166169
167170
Methods that may be overridden:
168171
169-
- server_bind()
170172
- server_activate()
171-
- get_request() -> request, client_address
172173
- handle_timeout()
173174
- verify_request(request, client_address)
174175
- server_close()
@@ -186,15 +187,11 @@ class BaseServer:
186187
instances:
187188
188189
- timeout
189-
- address_family
190-
- socket_type
191-
- allow_reuse_address
192-
- allow_reuse_port
193190
194191
Instance variables:
195192
193+
- server_address
196194
- RequestHandlerClass
197-
- socket
198195
199196
"""
200197

@@ -273,18 +270,16 @@ def service_actions(self):
273270
# - finish_request() instantiates the request handler class; this
274271
# constructor will handle the request all by itself
275272

273+
def _get_timeout(self):
274+
"""Hook so child classes can support other sources of timeout."""
275+
return self.timeout
276+
276277
def handle_request(self):
277278
"""Handle one request, possibly blocking.
278279
279280
Respects self.timeout.
280281
"""
281-
# Support people who used socket.settimeout() to escape
282-
# handle_request before self.timeout was available.
283-
timeout = self.socket.gettimeout()
284-
if timeout is None:
285-
timeout = self.timeout
286-
elif self.timeout is not None:
287-
timeout = min(timeout, self.timeout)
282+
timeout = self._get_timeout()
288283
if timeout is not None:
289284
deadline = time() + timeout
290285

@@ -325,6 +320,13 @@ def _handle_request_noblock(self):
325320
else:
326321
self.shutdown_request(request)
327322

323+
def get_request(self):
324+
"""Get the request and client address from the socket.
325+
326+
Must be overridden by subclasses.
327+
"""
328+
raise NotImplementedError
329+
328330
def handle_timeout(self):
329331
"""Called if no new request arrives within self.timeout.
330332
@@ -489,6 +491,16 @@ def server_close(self):
489491
"""
490492
self.socket.close()
491493

494+
def _get_timeout(self):
495+
# Support people who used socket.settimeout() to escape
496+
# handle_request before self.timeout was available.
497+
timeout = self.socket.gettimeout()
498+
if timeout is None:
499+
timeout = self.timeout
500+
elif self.timeout is not None:
501+
timeout = min(timeout, self.timeout)
502+
return timeout
503+
492504
def fileno(self):
493505
"""Return socket file number.
494506
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Updated documentation for :mod:`socketserver` to clarify the differences
2+
between :class:`socketserver.BaseServer` and
3+
:class:`socketserver.TCPServer`.

0 commit comments

Comments
 (0)