Package asycamore :: Module tcpsocket

Module tcpsocket



Implements the basic socket primitives usefull to most servers and clients

The primitives defined by this module are designed to be used in conjunction with the asynchronous dispatch api offered by asycamore.dispatcher

client application api

Consists of write_iterable and data_reader used in conjunction with asycamore.httpclientsocket.HTTPClientSocket. And connect_tcp used in conjunction with asycamore.dispatcher

For server model implementors

Consists of listen_tcp, server_accept and the class AcceptingSocket,

For all

socket_reader, socket_writer, getsockerr



Classes
  AcceptingSocket
A minimalist instance for managing an accepting server socket.
Functions
 
connect_tcp(o, address)
Initiate a nonblocking tcp connect.
 
data_reader(o, for_each=<function <lambda> at 0xb77401b4>, sentinel=<object object at 0xb7db5460>)
Provides a just call me with the data interface to socket reading
 
getsockerr(s)
Translate errors pending on the socket to a string representation.
 
listen_tcp(o, ip, port, backlog)
create and initialise a listening server socket.
 
server_accept(serverstate, connection_factory, connection_closer)
Accepts a connection on the socket associated with serverstate.
 
socket_reader(sock, sentinel=11, buffer_size=8192)
yield up to buffer size bytes on each iteration.
 
socket_writer(sock, sentinel=<object object at 0xb7db5460>)
Iterative driver for sending data to a socket.
 
write_iterable(o, iterable, for_each=<function <lambda> at 0xb7740144>, sentinel=<object object at 0xb7db5460>, before_and_after=False)
A client focused api for sending discrete data items to a socket.
Function Details

connect_tcp(o, address)

 

Initiate a nonblocking tcp connect.

If the connection attempt is successfully intiated o.dispatch_state is set to 'connecting'

For a succesfull connection result[0] is one of 0, socket.EINPROGRESS.

If result[0] == 0 it means the connection was established immediately, in this case it is the callers responsibility to deal with this. At the least the caller should simulate the connection event by invoking:

o.dispatch_event((True, False, None))

As o.dispatch_state is initialised by this function, all dispatch_event implementations can trivialy deal with this scenario. Most will need to take no special action. Those implementations that need to care about specific event flags or values for the Read, Write, Exceptional fields of the event can distinguish immediate connect as:

R is True and W is False and E is None

If the target host is on the same machine it is normal for the connect to complete immediately. The chosen value for the event flagging immediate connect is derived from following information from p 448 Unix Network Programming v1

  • Non blocking connects usualy complete immediately if the target server is on the same host.

Berkeley-derived implementations & POSIX, and p 531, 530 of TCPv2, have have the following two rules regarding select & nonblocking connect:

  1. On successfull connect, the descriptor becomes writeable.
  2. If an error occurs during connection establishment, the descriptor becomes both readable, and writeable.

data_reader(o, for_each=<function <lambda> at 0xb77401b4>, sentinel=<object object at 0xb7db5460>)

 

Provides a just call me with the data interface to socket reading

Similar to write_iterable in behaviour and use but much simpler. This function is used by client connection states to provide a call back interface for consuming data read from a socket. for_each is called with the non empty data that arrived for each not empty read event. A zero byte read will imediately close the connection.

listen_tcp(o, ip, port, backlog)

 

create and initialise a listening server socket.

server socket setup:
  • creates the socket
  • places it in non blocking mode
  • calls set_reuse_addr if possible
  • calls bind
  • calls listen

While we should be able to rely on select to be authoratative with regard to readability, making setblocking(0) redundant for a listening socket, we cant according to: p463 UNP v1.

server_accept(serverstate, connection_factory, connection_closer)

 

Accepts a connection on the socket associated with serverstate.

Then:

  • places it in non-blocking mode.
  • invokes connection_factory and returns the result to the caller

connection_factory is called like this:

connection_factory(sock, serverstate, connection_closer)
Parameters:
  • connection_factory - A callable that creates and intialises the transport socket and state for the accepted connection.

socket_reader(sock, sentinel=11, buffer_size=8192)

 

yield up to buffer size bytes on each iteration.

If an operation would block, yield sentinel. Returns on any error other than EAGAIN, EWOULDBLOCK, ENOBUFFS, EINTR. EAGAIN is assumed to be numericaly, and semanticaly, equivelent to EWOULDBLOCK - this is reliable for posix systems.

socket_writer(sock, sentinel=<object object at 0xb7db5460>)

 

Iterative driver for sending data to a socket.

Used by the implementation of write_iterable. Properly detects exceptional events and returns for any other than EINTR, EWOULDBLOCK, EAGAIN and ENOBUFFS. Note: The value for EWOULDBLOCK is assumed to be numericaly equal to EAGAIN. For posix systems this is reliable.

write_iterable(o, iterable, for_each=<function <lambda> at 0xb7740144>, sentinel=<object object at 0xb7db5460>, before_and_after=False)

 

A client focused api for sending discrete data items to a socket.

Instances of this generator are typicaly used to insulate client document processing facilities from the detailed semantics of responding to events produced by the asycamore.dispatcher iterate main loop and passed from there, via the asynwgi.dispatcher.IDispatchContext interface to individual IDispatchTarget instances.

Each iterable will typically be a generator that yields complete http requests all of which target the same origin server.

The client program main loop will arrange to create a connection that will instantiate this generator iterator with the connection state instance as the o parameter and the iterable and for_each callback provided by the document processing code.

Clients will typically be using asycamore.httpclientsocket.HTTPClientSocket to handle the connection state and that class makes use of this generator to handle writing application requests to the underlying socket.

Once a connection is established that connection will drive the write_iterable instance by sending in the events it receives in its dispatch_event method. The write_iterable instance procedes by taking items from the iterable and sending them to the socket object owned by the connection state. for_each is called once, with the value from the iterable as its only argument, after that entire value has been handed off to the socket.

If the boolean before_and_after is True for_each is additionaly invoked just before the sending starts and just after the first call made to send for that item. This enables a single for_each implementation to notice sending started sending complete conditions for each item produced by the iterable.

The for_each implementation must support two key word parameters: before_send and after_send and these should default to False. The for_each implementation can then reliably detect the all data has been sent condition as not before_send or after_send

A for_each body that detects all three call cases would look something like this:

if not before_send or after_send:
    nsent += 1
elif before_send:
    print 'about to start sending %s' % d
elif after_send:
    print 'started sending %d' % d

Example uses can be found in asycamore.httpclient, and, in particular, asycamore.httpclient.start_multiple_clients.