def finish(self):
"""Finishes the request."""
self._request_finished = True
+ # No more data is coming, so instruct TCP to send any remaining
+ # data immediately instead of waiting for a full packet or ack.
+ self.stream.set_nodelay(True)
if not self.stream.writing():
self._finish_request()
# directly, because in some cases the stream doesn't discover
# that it's closed until you try to read from it.
self.stream.read_until(b"\r\n\r\n", self._header_callback)
+
+ # Turn Nagle's algorithm back on, leaving the stream in its
+ # default state for the next request.
+ self.stream.set_nodelay(False)
except iostream.StreamClosedError:
self.close()
"""Returns true if the stream has been closed."""
return self._closed
+ def set_nodelay(self, value):
+ """Sets the no-delay flag for this stream.
+
+ By default, data written to TCP streams may be held for a time
+ to make the most efficient use of bandwidth (according to
+ Nagle's algorithm). The no-delay flag requests that data be
+ written as soon as possible, even if doing so would consume
+ additional bandwidth.
+
+ This flag is currently defined only for TCP-based ``IOStreams``.
+ """
+ pass
+
def _handle_events(self, fd, events):
if self.closed():
gen_log.warning("Got events for closed stream %d", fd)
self._run_callback(callback)
self._connecting = False
+ def set_nodelay(self, value):
+ if (self.socket is not None and
+ self.socket.family in (socket.AF_INET, socket.AF_INET6)):
+ self.socket.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_NODELAY, 1)
+
class SSLIOStream(IOStream):
"""A utility class to write to and read from a non-blocking SSL socket.
if b'\n' in line:
raise ValueError('Newline in header: ' + repr(line))
request_lines.append(line)
- self.stream.write(b"\r\n".join(request_lines) + b"\r\n\r\n")
+ request_str = b"\r\n".join(request_lines) + b"\r\n\r\n"
if self.request.body is not None:
- self.stream.write(self.request.body)
+ request_str += self.request.body
+ self.stream.set_nodelay(True)
+ self.stream.write(request_str)
self.stream.read_until_regex(b"\r?\n\r?\n", self._on_headers)
def _release(self):
"""
return False
+ def set_nodelay(self, value):
+ """Set the no-delay flag for this stream.
+
+ By default, small messages may be delayed and/or combined to minimize
+ the number of packets sent. This can sometimes cause 200-500ms delays
+ due to the interaction between Nagle's algorithm and TCP delayed
+ ACKs. To reduce this delay (at the expense of possibly increasing
+ bandwidth usage), call ``self.set_nodelay(True)`` once the websocket
+ connection is established.
+
+ See `.IOStream.set_nodelay` for additional details.
+ """
+ self.stream.set_nodelay(value)
+
def get_websocket_scheme(self):
"""Return the url scheme used for this request, either "ws" or "wss".