@@ -35,7 +35,7 @@ class except to start a server at the beginning of the process
35
35
from tornado import httputil
36
36
from tornado import ioloop
37
37
from tornado import iostream
38
- from tornado import netutil
38
+ from tornado . netutil import TCPServer
39
39
from tornado import process
40
40
from tornado import stack_context
41
41
from tornado .util import b , bytes_type
@@ -45,188 +45,6 @@ class except to start a server at the beginning of the process
45
45
except ImportError :
46
46
ssl = None
47
47
48
-
49
- class TCPServer (object ):
50
- r"""A non-blocking, single-threaded TCP server.
51
-
52
- `TCPServer` can serve SSL traffic with Python 2.6+ and OpenSSL.
53
- To make this server serve SSL traffic, send the ssl_options dictionary
54
- argument with the arguments required for the `ssl.wrap_socket` method,
55
- including "certfile" and "keyfile"::
56
-
57
- TCPServer(applicaton, ssl_options={
58
- "certfile": os.path.join(data_dir, "mydomain.crt"),
59
- "keyfile": os.path.join(data_dir, "mydomain.key"),
60
- })
61
-
62
- `TCPServer` initialization follows one of three patterns:
63
-
64
- 1. `listen`: simple single-process::
65
-
66
- server = TCPServer(app)
67
- server.listen(8888)
68
- IOLoop.instance().start()
69
-
70
- 2. `bind`/`start`: simple multi-process::
71
-
72
- server = TCPServer(app)
73
- server.bind(8888)
74
- server.start(0) # Forks multiple sub-processes
75
- IOLoop.instance().start()
76
-
77
- When using this interface, an `IOLoop` must *not* be passed
78
- to the `TCPServer` constructor. `start` will always start
79
- the server on the default singleton `IOLoop`.
80
-
81
- 3. `add_sockets`: advanced multi-process::
82
-
83
- sockets = tornado.netutil.bind_sockets(8888)
84
- tornado.process.fork_processes(0)
85
- server = TCPServer(app)
86
- server.add_sockets(sockets)
87
- IOLoop.instance().start()
88
-
89
- The `add_sockets` interface is more complicated, but it can be
90
- used with `tornado.process.fork_processes` to give you more
91
- flexibility in when the fork happens. `add_sockets` can
92
- also be used in single-process servers if you want to create
93
- your listening sockets in some way other than
94
- `tornado.netutil.bind_sockets`.
95
- """
96
- def __init__ (self , handle_stream , io_loop = None , ssl_options = None ):
97
- self .handle_stream = handle_stream
98
- self .io_loop = io_loop
99
- self .ssl_options = ssl_options
100
- self ._sockets = {} # fd -> socket object
101
- self ._pending_sockets = []
102
- self ._started = False
103
-
104
- def listen (self , port , address = "" ):
105
- """Starts accepting connections on the given port.
106
-
107
- This method may be called more than once to listen on multiple ports.
108
- `listen` takes effect immediately; it is not necessary to call
109
- `TCPServer.start` afterwards. It is, however, necessary to start
110
- the `IOLoop`.
111
- """
112
- sockets = netutil .bind_sockets (port , address = address )
113
- self .add_sockets (sockets )
114
-
115
- def add_sockets (self , sockets ):
116
- """Makes this server start accepting connections on the given sockets.
117
-
118
- The ``sockets`` parameter is a list of socket objects such as
119
- those returned by `tornado.netutil.bind_sockets`.
120
- `add_sockets` is typically used in combination with that
121
- method and `tornado.process.fork_processes` to provide greater
122
- control over the initialization of a multi-process server.
123
- """
124
- if self .io_loop is None :
125
- self .io_loop = ioloop .IOLoop .instance ()
126
-
127
- for sock in sockets :
128
- self ._sockets [sock .fileno ()] = sock
129
- netutil .add_accept_handler (sock , self ._handle_connection ,
130
- io_loop = self .io_loop )
131
-
132
- def add_socket (self , socket ):
133
- """Singular version of `add_sockets`. Takes a single socket object."""
134
- self .add_sockets ([socket ])
135
-
136
- def bind (self , port , address = None , family = socket .AF_UNSPEC , backlog = 128 ):
137
- """Binds this server to the given port on the given address.
138
-
139
- To start the server, call `start`. If you want to run this server
140
- in a single process, you can call `listen` as a shortcut to the
141
- sequence of `bind` and `start` calls.
142
-
143
- Address may be either an IP address or hostname. If it's a hostname,
144
- the server will listen on all IP addresses associated with the
145
- name. Address may be an empty string or None to listen on all
146
- available interfaces. Family may be set to either ``socket.AF_INET``
147
- or ``socket.AF_INET6`` to restrict to ipv4 or ipv6 addresses, otherwise
148
- both will be used if available.
149
-
150
- The ``backlog`` argument has the same meaning as for
151
- `socket.listen`.
152
-
153
- This method may be called multiple times prior to `start` to listen
154
- on multiple ports or interfaces.
155
- """
156
- sockets = netutil .bind_sockets (port , address = address ,
157
- family = family , backlog = backlog )
158
- if self ._started :
159
- self .add_sockets (sockets )
160
- else :
161
- self ._pending_sockets .extend (sockets )
162
-
163
- def start (self , num_processes = 1 ):
164
- """Starts this server in the IOLoop.
165
-
166
- By default, we run the server in this process and do not fork any
167
- additional child process.
168
-
169
- If num_processes is ``None`` or <= ``0``, we detect the number of cores
170
- available on this machine and fork that number of child
171
- processes. If num_processes is given and > ```1``, we fork that
172
- specific number of sub-processes.
173
-
174
- Since we use processes and not threads, there is no shared memory
175
- between any server code.
176
-
177
- Note that multiple processes are not compatible with the autoreload
178
- module (or the ``debug=True`` option to `tornado.web.Application`).
179
- When using multiple processes, no IOLoops can be created or
180
- referenced until after the call to ``TCPServer.start(n)``.
181
- """
182
- assert not self ._started
183
- self ._started = True
184
- if num_processes != 1 :
185
- process .fork_processes (num_processes )
186
- sockets = self ._pending_sockets
187
- self ._pending_sockets = []
188
- self .add_sockets (sockets )
189
-
190
- def stop (self ):
191
- """Stops listening for new connections.
192
-
193
- Requests currently in progress may still continue after the
194
- server is stopped.
195
- """
196
- for fd , sock in self ._sockets .iteritems ():
197
- self .io_loop .remove_handler (fd )
198
- sock .close ()
199
-
200
- def _handle_connection (self , connection , address ):
201
- if self .ssl_options is not None :
202
- assert ssl , "Python 2.6+ and OpenSSL required for SSL"
203
- try :
204
- connection = ssl .wrap_socket (connection ,
205
- server_side = True ,
206
- do_handshake_on_connect = False ,
207
- ** self .ssl_options )
208
- except ssl .SSLError , err :
209
- if err .args [0 ] == ssl .SSL_ERROR_EOF :
210
- return connection .close ()
211
- else :
212
- raise
213
- except socket .error , err :
214
- if err .args [0 ] == errno .ECONNABORTED :
215
- return connection .close ()
216
- else :
217
- raise
218
- try :
219
- if self .ssl_options is not None :
220
- stream = iostream .SSLIOStream (connection , io_loop = self .io_loop )
221
- else :
222
- stream = iostream .IOStream (connection , io_loop = self .io_loop )
223
- if connection .family not in (socket .AF_INET , socket .AF_INET6 ):
224
- # Unix (or other) socket; fake the remote address
225
- address = ('0.0.0.0' , 0 )
226
- self .handle_stream (stream , address )
227
- except Exception :
228
- logging .error ("Error in connection callback" , exc_info = True )
229
-
230
48
class HTTPServer (TCPServer ):
231
49
"""
232
50
A server is defined by a request callback that takes an HTTPRequest
@@ -273,9 +91,9 @@ def __init__(self, request_callback, no_keep_alive=False, xheaders=False,
273
91
self .request_callback = request_callback
274
92
self .no_keep_alive = no_keep_alive
275
93
self .xheaders = xheaders
276
- TCPServer .__init__ (self , self . _handle_stream , ** kwargs )
94
+ TCPServer .__init__ (self , ** kwargs )
277
95
278
- def _handle_stream (self , stream , address ):
96
+ def handle_stream (self , stream , address ):
279
97
HTTPConnection (stream , address , self .request_callback ,
280
98
self .no_keep_alive , self .xheaders )
281
99
@@ -292,6 +110,9 @@ class HTTPConnection(object):
292
110
def __init__ (self , stream , address , request_callback , no_keep_alive = False ,
293
111
xheaders = False ):
294
112
self .stream = stream
113
+ if self .stream .socket .family not in (socket .AF_INET , socket .AF_INET6 ):
114
+ # Unix (or other) socket; fake the remote address
115
+ address = ('0.0.0.0' , 0 )
295
116
self .address = address
296
117
self .request_callback = request_callback
297
118
self .no_keep_alive = no_keep_alive
0 commit comments