MCPcopy
hub / github.com/python-trio/trio / open_tcp_stream

Function open_tcp_stream

src/trio/_highlevel_open_tcp_stream.py:185–397  ·  view source on GitHub ↗

Connect to the given host and port over TCP. If the given ``host`` has multiple IP addresses associated with it, then we have a problem: which one do we use? One approach would be to attempt to connect to the first one, and then if that fails, attempt to connect to the second one .

(
    host: str | bytes,
    port: int,
    *,
    happy_eyeballs_delay: float | None = DEFAULT_DELAY,
    local_address: str | None = None,
)

Source from the content-addressed store, hash-verified

183# AF_INET6: "..."}
184# this might be simpler after
185async def open_tcp_stream(
186 host: str | bytes,
187 port: int,
188 *,
189 happy_eyeballs_delay: float | None = DEFAULT_DELAY,
190 local_address: str | None = None,
191) -> trio.SocketStream:
192 """Connect to the given host and port over TCP.
193
194 If the given ``host`` has multiple IP addresses associated with it, then
195 we have a problem: which one do we use?
196
197 One approach would be to attempt to connect to the first one, and then if
198 that fails, attempt to connect to the second one ... until we've tried all
199 of them. But the problem with this is that if the first IP address is
200 unreachable (for example, because it's an IPv6 address and our network
201 discards IPv6 packets), then we might end up waiting tens of seconds for
202 the first connection attempt to timeout before we try the second address.
203
204 Another approach would be to attempt to connect to all of the addresses at
205 the same time, in parallel, and then use whichever connection succeeds
206 first, abandoning the others. This would be fast, but create a lot of
207 unnecessary load on the network and the remote server.
208
209 This function strikes a balance between these two extremes: it works its
210 way through the available addresses one at a time, like the first
211 approach; but, if ``happy_eyeballs_delay`` seconds have passed and it's
212 still waiting for an attempt to succeed or fail, then it gets impatient
213 and starts the next connection attempt in parallel. As soon as any one
214 connection attempt succeeds, all the other attempts are cancelled. This
215 avoids unnecessary load because most connections will succeed after just
216 one or two attempts, but if one of the addresses is unreachable then it
217 doesn't slow us down too much.
218
219 This is known as a "happy eyeballs" algorithm, and our particular variant
220 is modelled after how Chrome connects to webservers; see `RFC 6555
221 <https://tools.ietf.org/html/rfc6555>`__ for more details.
222
223 Args:
224 host (str or bytes): The host to connect to. Can be an IPv4 address,
225 IPv6 address, or a hostname.
226
227 port (int): The port to connect to.
228
229 happy_eyeballs_delay (float or None): How many seconds to wait for each
230 connection attempt to succeed or fail before getting impatient and
231 starting another one in parallel. Set to `None` if you want
232 to limit to only one connection attempt at a time (like
233 :func:`socket.create_connection`). Default: 0.25 (250 ms).
234
235 local_address (None or str): The local IP address or hostname to use as
236 the source for outgoing connections. If ``None``, we let the OS pick
237 the source IP.
238
239 This is useful in some exotic networking configurations where your
240 host has multiple IP addresses, and you want to force the use of a
241 specific one.
242

Callers 6

setupFunction · 0.90
test_local_address_realFunction · 0.90
run_scenarioFunction · 0.90

Calls 7

waitMethod · 0.95
getaddrinfoFunction · 0.90
format_host_portFunction · 0.85
close_allFunction · 0.85
start_soonMethod · 0.80
removeMethod · 0.45

Tested by 6

setupFunction · 0.72
test_local_address_realFunction · 0.72
run_scenarioFunction · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…