ace v0.7.1 Ace.TCP.Server behaviour

Each Ace.TCP.Server manages a single TCP connection. They are responsible for managing communication between a TCP client and the larger application.

The server process accepts as well as manages the connection. There is no separate acceptor process. This means that that is no need to switch the connections owning process. Several erlang servers do use separate acceptor pools.

Example

The TCP.Server abstracts the common code required to manage a TCP connection. Developers only need to their own Server module to define app specific behaviour.

defmodule CounterServer do
  def init(_, num) do
    {:nosend, num}
  end

  def handle_packet(_, last) do
    count = last + 1
    {:send, "#{count}
", count}
  end

  def handle_info(_, last) do
    {:nosend, last}
  end
end

See the README.md for a complete overview on how to make a server available.

Summary

Types

The configuration used to start each server

Information about the servers connection to the client

The current state of an individual server process

Functions

Take provisioned server to accept the next connection on a socket

Start a new Ace.TCP.Server linked to the calling process

Callbacks

Every erlang message recieved by the server invokes this callback

Every packet recieved from the client invokes this callback

Invoked when a new client connects. accept/2 will block until a client connects and the server has initialised

Called whenever the connection is terminated

Types

app()
app :: {module, state}

The configuration used to start each server.

A server configuration consists of behaviour, the module, and state. The module should implement the Ace.TCP.Server behaviour. Any value can be passed as the state.

connection()
connection :: %{peer: {:inet.ip_address, :inet.port_number}}

Information about the servers connection to the client

state()
state :: term

The current state of an individual server process.

Functions

accept(server, listen_socket)
accept(server, :inet.socket) :: :ok when server: pid

Take provisioned server to accept the next connection on a socket.

Accept can only be called once for each server. After a connection has been closed the server will terminate.

start_link(app)
start_link(app) :: GenServer.on_start

Start a new Ace.TCP.Server linked to the calling process.

A server process is started with an app to describe handling connections. The app is a comination of behaviour and state app = {module, config}

The server process is returned immediatly. This is allow a supervisor to start several servers without waiting for connections.

A provisioned server will remain in an awaiting state until accept is called.

Callbacks

handle_info(term, state)
handle_info(term, state) ::
  {:send, term, state} |
  {:send, term, state, timeout} |
  {:nosend, state} |
  {:nosend, state, timeout} |
  {:close, state}

Every erlang message recieved by the server invokes this callback.

The return actions are the same as for the init/2 callback

handle_packet(binary, state)
handle_packet(binary, state) ::
  {:send, term, state} |
  {:send, term, state, timeout} |
  {:nosend, state} |
  {:nosend, state, timeout} |
  {:close, state}

Every packet recieved from the client invokes this callback.

The return actions are the same as for the init/2 callback

No additional packets will be taken from the socket until this callback returns

init(connection, state)
init(connection, state) ::
  {:send, iodata, state} |
  {:send, iodata, state, timeout} |
  {:nosend, state} |
  {:nosend, state, timeout} |
  {:close, state}

Invoked when a new client connects. accept/2 will block until a client connects and the server has initialised

The state is the second element in the app tuple that was used to start the endpoint.

Returning {:nosend, state} will setup a new server with internal state. The state is perserved in the process loop and passed as the second option to subsequent callbacks.

Returning {:nosend, state, timeout} is the same as {:send, state}. In addition handle_info(:timeout, state) will be called after timeout milliseconds, if no messages are received in that interval.

Returning {:send, message, state} or {:send, message, state, timeout} is similar to their :nosend counterparts, except the message is sent as the first communication to the client.

Returning {:close, state} will shutdown the server without any messages being sent or recieved

terminate(reason, state)
terminate(reason, state) :: term when reason: term

Called whenever the connection is terminated.