std.net.socket.TcpClient
type pub TcpClient
A TCP socket connected to another TCP socket.
Fields
socket
let pub @socket: Socket
The raw Socket
wrapped by this TcpClient
.
Static methods
new
Show source codeHide source code
fn pub static new(
ips: ref Array[IpAddress],
port: Int,
) -> Result[TcpClient, Error] {
with_timeout(ips, port, Duration.from_secs(5))
}
fn pub static new(ips: ref Array[IpAddress], port: Int) -> Result[TcpClient, Error]
Creates a new TcpClient
that's connected to an IP address and port number,
using a default timeout.
This method uses a default timeout of 5 seconds. If you wish to use a
custom timeout/deadline, use TcpClient.with_timeout
instead.
For more details, refer to the documentation of TcpClient.with_timeout
.
Examples
import std.net.socket (TcpClient)
import std.net.ip (IpAddress)
TcpClient.new([IpAddress.v4(127, 0, 0, 1)], port: 40_000).get
with_timeout
Show source codeHide source code
fn pub static with_timeout[T: ToInstant](
ips: ref Array[IpAddress],
port: Int,
timeout_after: ref T,
) -> Result[TcpClient, Error] {
happy.connect(ips, port, timeout_after.to_instant)
}
fn pub static with_timeout[T: ToInstant](ips: ref Array[IpAddress], port: Int, timeout_after: ref T) -> Result[TcpClient, Error]
Creates a new TcpClient
but limits the amount of time spent waiting for
the connection to be established.
The timeout_after
argument specifies the deadline after which the
connect()
system call times out. This deadline is not inherited by the
returned TcpClient
.
Connecting to multiple IP addresses
If multiple IP addresses are given, this method attempts to connect to them in accordance with RFC 8305 (also known as "Happy Eyeballs version 2"), with the following differences:
- DNS requests are performed separately and thus not subject to the Happy Eyeballs algorithm.
- We always interleave IPv6 and IPv4 addresses, starting with an IPv6
address (so
IPv6, IPv4, IPv6, IPv4, ...
). - There's no way to configure this behavior, nor is it planned to add the ability to do so.
Errors
If the connection can't be established, a std.io.Error
error is returned.
If ips
contains multiple IP addresses and a connection can't be
established to any of the addresses, one of the following errors is
returned:
Error.ConnectionRefused
if no connection could be established before the deadline expiredError.TimedOut
if the deadline expired
If ips
is empty, an Error.InvalidArgument
error is returned instead of
producing a panic. This is to allow handling of cases where one passes the
output of e.g. std.net.dns.Resolver.resolve
directly to this method
without checking if the DNS record actually contains any IP addresses.
Examples
import std.net.socket (TcpClient)
import std.net.ip (IpAddress)
import std.time (Duration)
TcpClient
.with_timeout(
ips: [IpAddress.v4(0, 0, 0, 0)],
port: 40_000,
timeout_after: Duration.from_secs(5)
)
.get
Instance methods
flush
Show source codeHide source code
fn pub mut flush -> Result[Nil, Error] {
Result.Ok(nil)
}
fn pub mut flush -> Result[Nil, Error]
Flushes any pending writes to the file system.
Flushing writes is a potentially expensive operation, and unnecessarily calling this method may degrade performance.
When flushing data to disk it's important to remember that the actual behaviour may vary based on the type of file system, operating system and storage hardware that's used. In particular, it's possible for one of these components to say "Yup, I totally flushed the data, you're all good!" when in fact they have not fully flushed the data.
local_address
Show source codeHide source code
fn pub local_address -> Result[SocketAddress, Error] {
@socket.local_address
}
fn pub local_address -> Result[SocketAddress, Error]
Returns the local address of this socket.
See the documentation of Socket.local_address
for more information.
peer_address
Show source codeHide source code
fn pub peer_address -> Result[SocketAddress, Error] {
@socket.peer_address
}
fn pub peer_address -> Result[SocketAddress, Error]
Returns the peer address of this socket.
See the documentation of Socket.peer_address
for more information.
Show source codeHide source code
fn pub mut print[B: Bytes](bytes: ref B) -> Result[Nil, E] {
try write(bytes)
write('\n')
}
fn pub mut print[B: Bytes](bytes: ref B) -> Result[Nil, E]
Writes the entirety of bytes
to the underlying stream, followed by
a Unix newline.
read
Show source codeHide source code
fn pub mut read(into: mut ByteArray, size: Int) -> Result[Int, Error] {
@socket.read(into, size)
}
fn pub mut read(into: mut ByteArray, size: Int) -> Result[Int, Error]
Reads up to size
bytes from self
into the given ByteArray
, returning
the number of bytes read.
The into
argument is the ByteArray
to read the bytes into. The capacity
of this ByteArray
is increased automatically if necessary.
The size
argument specifies how many bytes are to be read.
The return value is the number of bytes read.
The number of bytes read may be less than size
. This can happen for
different reasons, such as when all input is consumed or not enough data is
available (yet).
read_all
Show source codeHide source code
fn pub mut read_all(bytes: mut ByteArray) -> Result[Int, E] {
let mut total = 0
let mut read_size = INITIAL_READ_ALL_SIZE
loop {
match read(into: bytes, size: read_size) {
case Ok(0) -> return Result.Ok(total)
case Ok(n) -> {
total += n
# To reduce the number of calls to `Reader.read` when there's lots of
# input to consume, we increase the read size if deemed beneficial.
if read_size < MAX_READ_ALL_SIZE and n == read_size { read_size *= 2 }
}
case Error(e) -> throw e
}
}
}
fn pub mut read_all(bytes: mut ByteArray) -> Result[Int, E]
Reads from self
into the given ByteArray
, returning when all input is
consumed.
The return value is the number of bytes read.
Errors
This method returns an Error
if the underlying call to Read.read
returns
an Error
.
read_exact
Show source codeHide source code
fn pub mut read_exact(
into: mut ByteArray,
size: Int,
) -> Result[Nil, ReadExactError[E]] {
let mut pending = size
while pending > 0 {
match read(into, pending) {
case Ok(0) if pending > 0 -> throw ReadExactError.EndOfInput
case Ok(n) -> pending -= n
case Error(e) -> throw ReadExactError.Read(e)
}
}
Result.Ok(nil)
}
fn pub mut read_exact(into: mut ByteArray, size: Int) -> Result[Nil, ReadExactError[E]]
Reads exactly size
bytes into into
.
Whereas Read.read
might return early if fewer bytes are available in the
input stream, Read.read_exact
continues reading until the desired amount
of bytes is read.
Errors
If the end of the input stream is encountered before filling the buffer, an
Error.EndOfInput
error is returned.
If an error is returned, no assumption can be made about the state of the
into
buffer, i.e. there's no guarantee data read so far is in the buffer
in the event of an error.
shutdown
Show source codeHide source code
fn pub mut shutdown -> Result[Nil, Error] {
@socket.shutdown
}
fn pub mut shutdown -> Result[Nil, Error]
Shuts down both the reading and writing half of this socket.
shutdown_read
Show source codeHide source code
fn pub mut shutdown_read -> Result[Nil, Error] {
@socket.shutdown_read
}
fn pub mut shutdown_read -> Result[Nil, Error]
Shuts down the reading half of this socket.
shutdown_write
Show source codeHide source code
fn pub mut shutdown_write -> Result[Nil, Error] {
@socket.shutdown_write
}
fn pub mut shutdown_write -> Result[Nil, Error]
Shuts down the writing half of this socket.
try_clone
Show source codeHide source code
fn pub try_clone -> Result[TcpClient, Error] {
@socket.try_clone.map(fn (sock) { TcpClient(sock) })
}
fn pub try_clone -> Result[TcpClient, Error]
Attempts to clone the socket.
Cloning a socket may fail, such as when the program has too many open file descriptors.
write
Show source codeHide source code
fn pub mut write[B: Bytes](bytes: ref B) -> Result[Nil, Error] {
@socket.write(bytes)
}
fn pub mut write[B: Bytes](bytes: ref B) -> Result[Nil, Error]
Writes the entirety of bytes
to the underlying stream.
Types implementing this method must guarantee that upon returning from this
method, either all of the data is written and a Ok(Nil)
is returned, or
an Error
is returned.
Implemented traits
Read
impl Read[Error] for TcpClient
Write
impl Write[Error] for TcpClient