BaseServer 源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
class
BaseServer:
"""Base class for server classes.
Methods for the caller:
- __init__(server_address, RequestHandlerClass)
- serve_forever(poll_interval=0.5)
- shutdown()
- handle_request() # if you do not use serve_forever()
- fileno() -> int # for select()
Methods that may be overridden:
- server_bind()
- server_activate()
- get_request() -> request, client_address
- handle_timeout()
- verify_request(request, client_address)
- server_close()
- process_request(request, client_address)
- shutdown_request(request)
- close_request(request)
- handle_error()
Methods for derived classes:
- finish_request(request, client_address)
Class variables that may be overridden by derived classes or
instances:
- timeout
- address_family
- socket_type
- allow_reuse_address
Instance variables:
- RequestHandlerClass
- socket
"""
timeout
=
None
def
__init__(
self
, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self
.server_address
=
server_address
self
.RequestHandlerClass
=
RequestHandlerClass
self
.__is_shut_down
=
threading.Event()
self
.__shutdown_request
=
False
def
server_activate(
self
):
"""Called by constructor to activate the server.
May be overridden.
"""
pass
def
serve_forever(
self
, poll_interval
=
0.5
):
"""Handle one request at a time until shutdown.
Polls for shutdown every poll_interval seconds. Ignores
self.timeout. If you need to do periodic tasks, do them in
another thread.
"""
self
.__is_shut_down.clear()
try
:
while
not
self
.__shutdown_request:
# XXX: Consider using another file descriptor or
# connecting to the socket to wake this up instead of
# polling. Polling reduces our responsiveness to a
# shutdown request and wastes cpu at all other times.
r, w, e
=
_eintr_retry(select.select, [
self
], [], [],
poll_interval)
if
self
in
r:
self
._handle_request_noblock()
finally
:
self
.__shutdown_request
=
False
self
.__is_shut_down.
set
()
def
shutdown(
self
):
"""Stops the serve_forever loop.
Blocks until the loop has finished. This must be called while
serve_forever() is running in another thread, or it will
deadlock.
"""
self
.__shutdown_request
=
True
self
.__is_shut_down.wait()
# The distinction between handling, getting, processing and
# finishing a request is fairly arbitrary. Remember:
#
# - handle_request() is the top-level call. It calls
# select, get_request(), verify_request() and process_request()
# - get_request() is different for stream or datagram sockets
# - process_request() is the place that may fork a new process
# or create a new thread to finish the request
# - finish_request() instantiates the request handler class;
# this constructor will handle the request all by itself
def
handle_request(
self
):
"""Handle one request, possibly blocking.
Respects self.timeout.
"""
# Support people who used socket.settimeout() to escape
# handle_request before self.timeout was available.
timeout
=
self
.socket.gettimeout()
if
timeout
is
None
:
timeout
=
self
.timeout
elif
self
.timeout
is
not
None
:
timeout
=
min
(timeout,
self
.timeout)
fd_sets
=
_eintr_retry(select.select, [
self
], [], [], timeout)
if
not
fd_sets[
0
]:
self
.handle_timeout()
return
self
._handle_request_noblock()
def
_handle_request_noblock(
self
):
"""Handle one request, without blocking.
I assume that select.select has returned that the socket is
readable before this function was called, so there should be
no risk of blocking in get_request().
"""
try
:
request, client_address
=
self
.get_request()
except
socket.error:
return
if
self
.verify_request(request, client_address):
try
:
self
.process_request(request, client_address)
except
:
self
.handle_error(request, client_address)
self
.shutdown_request(request)
def
handle_timeout(
self
):
"""Called if no new request arrives within self.timeout.
Overridden by ForkingMixIn.
"""
pass
def
verify_request(
self
, request, client_address):
"""Verify the request. May be overridden.
Return True if we should proceed with this request.
"""
return
True
def
process_request(
self
, request, client_address):
"""Call finish_request.
Overridden by ForkingMixIn and ThreadingMixIn.
"""
self
.finish_request(request, client_address)
self
.shutdown_request(request)
def
server_close(
self
):
"""Called to clean-up the server.
May be overridden.
"""
pass
def
finish_request(
self
, request, client_address):
"""Finish one request by instantiating RequestHandlerClass."""
self
.RequestHandlerClass(request, client_address,
self
)
def
shutdown_request(
self
, request):
"""Called to shutdown and close an individual request."""
self
.close_request(request)
def
close_request(
self
, request):
"""Called to clean up an individual request."""
pass
def
handle_error(
self
, request, client_address):
"""Handle an error gracefully. May be overridden.
The default is to print a traceback and continue.
"""
print
'-'
*
40
print
'Exception happened during processing of request from'
,
print
client_address
import
traceback
traceback.print_exc()
# XXX But this goes to stderr!
print
'-'
*
40
|
TCPServer源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
class
TCPServer(BaseServer):
"""Base class for various socket-based server classes.
Defaults to synchronous IP stream (i.e., TCP).
Methods for the caller:
- __init__(server_address, RequestHandlerClass, bind_and_activate=True)
- serve_forever(poll_interval=0.5)
- shutdown()
- handle_request() # if you don't use serve_forever()
- fileno() -> int # for select()
Methods that may be overridden:
- server_bind()
- server_activate()
- get_request() -> request, client_address
- handle_timeout()
- verify_request(request, client_address)
- process_request(request, client_address)
- shutdown_request(request)
- close_request(request)
- handle_error()
Methods for derived classes:
- finish_request(request, client_address)
Class variables that may be overridden by derived classes or
instances:
- timeout
- address_family
- socket_type
- request_queue_size (only for stream sockets)
- allow_reuse_address
Instance variables:
- server_address
- RequestHandlerClass
- socket
"""
address_family
=
socket.AF_INET
socket_type
=
socket.SOCK_STREAM
request_queue_size
=
5
allow_reuse_address
=
False
def
__init__(
self
, server_address, RequestHandlerClass, bind_and_activate
=
True
):
"""Constructor. May be extended, do not override."""
BaseServer.__init__(
self
, server_address, RequestHandlerClass)
self
.socket
=
socket.socket(
self
.address_family,
self
.socket_type)
if
bind_and_activate:
try
:
self
.server_bind()
self
.server_activate()
except
:
self
.server_close()
raise
def
server_bind(
self
):
"""Called by constructor to bind the socket.
May be overridden.
"""
if
self
.allow_reuse_address:
self
.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
1
)
self
.socket.bind(
self
.server_address)
self
.server_address
=
self
.socket.getsockname()
def
server_activate(
self
):
"""Called by constructor to activate the server.
May be overridden.
"""
self
.socket.listen(
self
.request_queue_size)
def
server_close(
self
):
"""Called to clean-up the server.
May be overridden.
"""
self
.socket.close()
def
fileno(
self
):
"""Return socket file number.
Interface required by select().
"""
return
self
.socket.fileno()
def
get_request(
self
):
"""Get the request and client address from the socket.
May be overridden.
"""
return
self
.socket.accept()
def
shutdown_request(
self
, request):
"""Called to shutdown and close an individual request."""
try
:
#explicitly shutdown. socket.close() merely releases
#the socket and waits for GC to perform the actual close.
request.shutdown(socket.SHUT_WR)
except
socket.error:
pass
#some platforms may raise ENOTCONN here
self
.close_request(request)
def
close_request(
self
, request):
"""Called to clean up an individual request."""
request.close()
|
ThreadingMixIn源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class
ThreadingMixIn:
"""Mix-in class to handle each request in a new thread."""
# Decides how threads will act upon termination of the
# main process
daemon_threads
=
False
def
process_request_thread(
self
, request, client_address):
"""Same as in BaseServer but as a thread.
In addition, exception handling is done here.
"""
try
:
self
.finish_request(request, client_address)
self
.shutdown_request(request)
except
:
self
.handle_error(request, client_address)
self
.shutdown_request(request)
def
process_request(
self
, request, client_address):
"""Start a new thread to process the request."""
t
=
threading.Thread(target
=
self
.process_request_thread,
args
=
(request, client_address))
t.daemon
=
self
.daemon_threads
t.start()
|
ThreadingTCPServer源码:
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
pass
BaseRequestHandler源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
class
BaseRequestHandler:
"""Base class for request handler classes.
This class is instantiated for each request to be handled. The
constructor sets the instance variables request, client_address
and server, and then calls the handle() method. To implement a
specific service, all you need to do is to derive a class which
defines a handle() method.
The handle() method can find the request as self.request, the
client address as self.client_address, and the server (in case it
needs access to per-server information) as self.server. Since a
separate instance is created for each request, the handle() method
can define arbitrary other instance variariables.
"""
def
__init__(
self
, request, client_address, server):
self
.request
=
request
self
.client_address
=
client_address
self
.server
=
server
self
.setup()
try
:
self
.handle()
finally
:
self
.finish()
def
setup(
self
):
pass
def
handle(
self
):
pass
def
finish(
self
):
pass
|
本文转自027ryan 51CTO博客,原文链接:http://blog.51cto.com/ucode/1764215
,如需转载请自行联系原作者