Socket I/O

Note

Socket subclasses IOChannel but for convenience all superclass methods and properties are shown below.

See IOChannel for more information on internal details.

class kaa.Socket(buffer_size=None, chunk_size=1048576)

Communicate over TCP or Unix sockets, implementing fully asynchronous reads and writes.

kaa.Socket requires an IPv6-capable stack, and favors IPv6 connectivity when available. This should generally be completely transparent on IPv4-only networks. See connect() for more information.

Synopsis

Class Hierarchy

kaa.Object
└─ kaa.IOChannel
     └─ kaa.Socket

Methods
accept()
close()Closes the channel.
connect()Connects to the host specified in address.
create_connection()
listen()Set the socket to accept incoming connections.
make_native_proxy()
normalize_address()Converts supported address formats into a normalized 4-tuple (hostname, port, flowinfo, scope). See connect() and listen() for supported formats.
read()Reads a chunk of data from the channel.
readline()Reads a line from the channel.
steal()
wrap()Wraps an existing low-level socket object.
write()Writes the given data to the channel.
Properties
aliveread-onlyTrue if the socket is connected, listening, or connecting.
auto_acceptread/writeIf True (default), automatically accept new clients connecting to listening sockets.
buffer_sizeread/writeSize of the send and receive socket buffers (SO_SNDBUF and SO_RCVBUF) in bytes.
channelread-onlyThe original object this IOChannel is wrapping.
chunk_sizeread/writeNumber of bytes to attempt to read from the channel at a time.
close_on_eofread/writeWhether the channel automatically closes when EOF is encountered or on unexpected exceptions.
connectedread-onlyTrue when the socket is currently connected to a peer.
connectingread-onlyTrue if the socket is in the process of establishing a connection but is not yet connected.
delimiterread/writeString used to split data for use with readline().
filenoread-only
listeningread-onlyTrue if this is a listening socket, and False otherwise.
localread-onlyInformation about the local side of the socket.
moderead-onlyWhether the channel is read-only, or read/write.
peerread-onlyInformation about the remote side of the socket.
queue_sizeread/writeThe size limit in bytes for the read and write queues.
read_queue_usedread-onlyThe number of bytes in the read queue.
readableread-onlyTrue if read() may be called.
writableread-onlyTrue if write() may be called.
write_queue_usedread-onlyThe number of bytes queued in memory to be written to the channel.
Signals
readEmitted for each chunk of data read from the channel.
new-client-connectingEmitted when a new client is attempting to connect to a listening socket, but before the connection is accepted.
readlineEmitted for each line read from the channel.
new-clientEmitted when a new client connects to a listening socket.
closedEmitted when the channel is closed.

Methods

accept()
close(immediate=False, expected=True)

Closes the channel.

Parameters:immediate (bool) – if False and there is data in the write buffer, the channel is closed once the write buffer is emptied. Otherwise the channel is closed immediately and the closed signal is emitted.
connect(addr, source_address=None, ipv6=True)

Connects to the host specified in address.

Parameters:
  • addr (str, or 2- or 4-tuple) – Address for a remote host, or a Unix socket. If a str, it is either a Unix socket path or represents a TCP socket when in the form host:service[%scope]. See below for further details.
  • ipv6 – if True, will connect to the remote host using IPv6 if it is reachable via IPv6. This is perfectly safe for IPv4 only hosts too. Set this to False if the remote host has a AAAA record and the local host has an IPv6 route to it, but you want to force IPv4 anyway.
Returns:

An InProgress object.

If addr is given as a 4-tuple, it is in the form (host, service, flowinfo, scope). If given as a 2-tuple, it is in the form (host, service), and in this case the flowinfo and scope are assumed to be 0.

The flowinfo and scope fields are only relevant for IPv6 hosts, where they represent the sin6_flowinfo and sin6_scope_id members in struct sockaddr_in6 in C. scope may be the name of an interface (e.g. eth0) or an interface id, and is needed when connecting to link-local addresses (fe80::/16).

If addr is given as a string, it is treated as a Unix socket path if it does not contain :, otherwise it is specified as host:service[%scope], where [x] indicates that x is optional, and where:

  • host is a hostname, an IPv4 dotted quad, or an IPv6 address wrapped in square brackets. e.g. freevo.org, 192.168.0.1, [3000::1]
  • service is a service name or port number. e.g. http, 80
  • scope is an interface name or number. e.g. eth0, 2

When connecting to a link-local address (fe80::/16), scope must be specified. Relative Unix socket names (those not prefixed with /) are created via kaa.tempfile().

This function is executed in a thread to avoid blocking. It therefore returns an InProgress object. If the socket is connected, the InProgress is finished with no arguments. If the connection cannot be established, an exception is thrown to the InProgress.

static create_connection(addr=None, timeout=<object object at 0x2b8d872202a0>, source_address=None, overwrite=False, ipv6=True)
listen(addr, backlog=5, ipv6=True)

Set the socket to accept incoming connections.

Parameters:
  • addr (int, str, or 2- or 4-tuple) – Binds the socket to this address. If an int, this specifies a TCP port that is bound on all interfaces; if a str, it is either a Unix socket path or represents a TCP socket when in the form [host]:[service][%scope]. See below for further details.
  • backlog (int) – the maximum length to which the queue of pending connections for the socket may grow.
  • ipv6 (bool) – if True, will prefer binding to IPv6 addresses if addr is a hostname that contains both AAAA and A records. If addr is specified as an IP address, this argument does nothing.
Raises :

ValueError if addr is invalid, or socket.error if the bind fails.

If addr is given as a 4-tuple, it is in the form (host, service, flowinfo, scope). If passed as a 2-tuple, it is in the form (host, service), and in this case, it is assumed that flowinfo and scope are both 0. See connect() for more information.

If host is given as a string, it is treated as a Unix socket path if it does not contain :, otherwise it is specified as [host]:[service][%scope], where [x] indicates that x is optional, and where:

  • host is a hostname, an IPv4 dotted quad, or an IPv6 address wrapped in square brackets. e.g. localhost, 192.168.0.1, [3000::1]. If host is not specified, the socket will listen on all interfaces.
  • service is a service name or port number. e.g. http, 80
  • scope is an interface name or number. e.g. eth0, 2

When binding to a link-local address (fe80::/16), scope must be specified. Relative Unix socket names (those not prefixed with /) are created via kaa.tempfile.

Warning

If the bind address supplied is a hostname rather than an IPv4 or IPv6 address, this function will block in order to resolve the hostname if the name is not specified in /etc/hosts. (In other words, localhost is probably safe.)

Once listening, new connections are automatically accepted, and the new-client signal is emitted for each new connection. Callbacks connecting to the signal will receive a new Socket object representing the client connection.

make_native_proxy(close_on_eof=None)
static normalize_address(addr)

Converts supported address formats into a normalized 4-tuple (hostname, port, flowinfo, scope). See connect() and listen() for supported formats.

Service names are resolved to port numbers, and interface names are resolved to scope ids. However, hostnames are not resolved to IPs since that can block. Unspecified port or interface name will produced 0 values for those fields.

A non-absolute unix socket name will converted to a full path using kaa.tempfile().

If we can’t make sense of the given address, a ValueError exception will be raised.

read()

Reads a chunk of data from the channel.

Returns:An InProgress object. If the InProgress is finished with the empty string, it means that no data was collected and the channel was closed (or the channel was already closed when read() was called).

It is therefore possible to busy-loop by reading on a closed channel:

while True:
    data = yield channel.read()
    # Or: channel.read().wait()

So the return value of read() should be checked. Alternatively, the readable property could be tested:

while channel.readable:
     data = yield process.read()
readline()

Reads a line from the channel.

The line delimiter is included in the string to avoid ambiguity. If no delimiter is present then either the read queue became full or the channel was closed before a delimiter was received.

Returns:An InProgress object. If the InProgress is finished with the empty string, it means that no data was collected and the channel was closed (or the channel was already closed when readline() was called).

Data from the channel is read and queued in until the delimiter (\n by default, but may be changed by the delimiter property) is found. If the read queue size exceeds the queue limit, then the InProgress returned here will be finished prematurely with whatever is in the read queue, and the read queue will be purged.

This method may not be called when a callback is connected to the IOChannel’s readline signal. You must use either one approach or the other.

steal(socket)
wrap(sock, mode=3)

Wraps an existing low-level socket object.

addr specifies the 4-tuple address corresponding to the socket.

write(data)

Writes the given data to the channel.

Parameters:data (string) – the data to be written to the channel.
Returns:An InProgress object which is finished when the given data is fully written to the channel. The InProgress is finished with the number of bytes sent in the last write required to commit the given data to the channel. (This may not be the actual number of bytes of the given data.)

If the channel closes unexpectedly before the data was written, an IOError is thrown to the InProgress.

It is not required that the channel be open in order to write to it. Written data is queued until the channel open and then flushed. As writes are asynchronous, all written data is queued. It is the caller’s responsibility to ensure the internal write queue does not exceed the desired size by waiting for past write() InProgress to finish before writing more data.

If a write does not complete because the channel was closed prematurely, an IOError is thrown to the InProgress.

Properties

alive

True if the socket is connected, listening, or connecting.

auto_accept

If True (default), automatically accept new clients connecting to listening sockets.

See listen() for more details.

buffer_size

Size of the send and receive socket buffers (SO_SNDBUF and SO_RCVBUF) in bytes.

Setting this to higher values (say 1M) improves performance when sending large amounts of data across the socket. Note that the upper bound may be restricted by the kernel. (Under Linux, this can be tuned by adjusting /proc/sys/net/core/[rw]mem_max)

channel

The original object this IOChannel is wrapping.

This may be a file object, socket object, file descriptor, etc., depending what was passed during initialization or to wrap().

This is None if the channel is closed.

chunk_size

Number of bytes to attempt to read from the channel at a time.

The default is 1M. A ‘read’ signal is emitted for each chunk read from the channel. (The number of bytes read at a time may be less than the chunk size, but will never be more.)

close_on_eof

Whether the channel automatically closes when EOF is encountered or on unexpected exceptions.

The channel is considered EOF when a read returns an empty string. A write that fails due to IOError or OSError will also close the channel if this property is True.

This behaviour makes sense for stream-based channels (e.g. a subprocess or socket), but may not for file-based channels. The default is True unless the underlying wrapped channel object contains a seek method, in which case it is treated as a file and this property is False. In either case it can be overridden by explicitly setting this property.

connected

True when the socket is currently connected to a peer.

When a socket is in the process of connecting, it is not considered connected, although it is considered alive.

Note

This property will not change until a read() or write() is attempted on the socket. Only then can it be determined if the socket has disconnected.

Warning

When you want to read all data from the socket until it closes, you should use the readable property instead.

connecting

True if the socket is in the process of establishing a connection but is not yet connected.

Once the socket is connected, the connecting property will be False, but the connected property will be True.

delimiter

String used to split data for use with readline().

Delimiter may also be a list of strings, in which case any one of the elements in the list will be used as a delimiter. For example, if you want to delimit based on either \r or \n, specify [‘\r’, ‘\n’].

fileno
listening

True if this is a listening socket, and False otherwise.

local

Information about the local side of the socket.

This is either the tuple (host, port, flowinfo, scopeid, scope) representing the local end of a TCP socket, or the string containing the name of a Unix socket.

scope is the interface name represented by scopeid, and is None if scopeid is 0.

On Python 2.6 and later, the returned value is a namedtuple.

mode

Whether the channel is read-only, or read/write.

A bitmask of IO_READ and/or IO_WRITE.

peer

Information about the remote side of the socket.

This is a tuple (host, port, flowinfo, scopeid, scope, reqhost) representing the remote end of the socket.

scope is the interface name represented by scopeid, and is None if scopeid is 0. reqhost is the requested hostname if connect() was called, or None if this is a listening socket.

On Python 2.6 and later, the returned value is a namedtuple.

queue_size

The size limit in bytes for the read and write queues.

Each queue can consume at most this size plus the chunk size. Setting a value does not affect any data currently in any of the the queues.

read_queue_used

The number of bytes in the read queue.

The read queue is only used if either readline() or the readline signal is.

readable

True if read() may be called.

A socket is considered readable when it is alive, or if it’s closed but there is buffered data to be read.

Because of the presence of a read buffer, you should test this property to determine if you should read(), not the connected property:

while socket.readable:
    data = yield socket.read()
    [...]

Note

A value of True does not mean there is data available, but rather that there could be and that a read() call is possible (however that read() call may return None, in which case the readable property will subsequently be False because the socket is disconnected).

writable

True if write() may be called.

(However, if you pass too much data to write() such that the write queue limit is exceeded, the write will fail.)

write_queue_used

The number of bytes queued in memory to be written to the channel.

Signals

read

Emitted for each chunk of data read from the channel.

def callback(chunk, ...)
Param chunk:data read from the channel
Type chunk:str

When a callback is connected to the read signal, data is automatically read from the channel as soon as it becomes available, and the signal is emitted.

It is allowed to have a callback connected to the read signal and simultaneously use the read() and readline() methods.

new-client-connecting

Emitted when a new client is attempting to connect to a listening socket, but before the connection is accepted.

def callback(...)

If auto_accept is True (default), this signal can be used to prevent the client connection by returning False from the callback. If False, the callback must explicitly call listen() or the client will not be connected.

readline

Emitted for each line read from the channel.

def callback(line, ...)
Param line:line read from the channel
Type line:str

It is not allowed to have a callback connected to the readline signal and simultaneously use the readline() method.

Refer to readline() for more details.

new-client

Emitted when a new client connects to a listening socket.

def callback(client, ...)

Parameters:client (Socket object) – the new client that just connected.
closed

Emitted when the channel is closed.

def callback(expected, ...)
Param expected:True if the channel is closed because close() was called.
Type expected:bool

Previous topic

I/O Channels

Next topic

Sub-Process I/O

This Page