Ace
Ace server for managing TCP endpoints and connections.
I tackled this project as an interesting Elixir exercise and to learn about TCP. The code is designed to be accessible and is thoroughly commented.
For more details look at Ace 0.1.
If you are looking for a production webserver I would recommend one of:
Introduction
TCP endpoints are started with a pool of acceptors. Servers are started on demand for each client connection.
Many servers one client, NOT many clients one server.
Ace is responsible for managing server processes. Server modules describe the communication patterns with clients.
Documentation for Ace is available on hexdoc
Installation
Available on Hex, the package can be installed as:
Add
ace
to your list of dependencies inmix.exs
:def deps do [{:ace, "~> 0.6.3"}] end
Usage
Ace manages TCP connections by refering to a user defined server behaviour. An Ace server must implement 4 callbacks:
init(connection, configuration)
for establishing a new connection.handle_packet(packet, state)
to handle incomming TCP packets.handle_info(message, state)
to handle application messages sent to the server.terminate
to do any cleanup when the connection is closed.
Server
Example server.
defmodule MyServer do
def init(_connection, state = {:greeting, greeting}) do
{:send, greeting, state}
end
def handle_packet(inbound, state) do
{:send, "ECHO: #{String.strip(inbound)}\r\n", state}
end
def handle_info({:notify, notification}, state) do
{:send, "#{notification}\r\n", state}
end
def terminate(_reason, _state) do
IO.puts("Socket connection closed")
end
end
Defining MyServer
above we can use it to start an Ace endpoint.
Quick start
From the console, start mix.
iex -S mix
In the iex
console, start a TCP endpoint.
app = {MyServer, {:greeting, "WELCOME"}}
{:ok, pid} = Ace.TCP.start_link(app, port: 8080)
Embedded endpoints
It is not a good idea to start unsupervised processes. For this reason an Ace endpoint can be added to you application supervision tree.
children = [
worker(Ace.TCP, [{MyServer, {:greeting, "WELCOME"}}, [port: 8080]])
]
Supervisor.start_link(children, opts)
See “01 Quote of the Day” for an example setup.
Connect
Use telnet to communicate with the server.
telnet localhost 8080
Wihin the telnet terminal.
# once connected
WELCOME
hi
ECHO: hi
In the iex session.
send(server, {:notify, "BOO!"})
back in telnet terminal.
BOO!
The plan
- To take this obviously deficient TCP echo server that I wrote as a beginner elixir developer and create a fully fledged HTTP server.
- Keep reasonable notes of progress so others can learn about how to build a web server in elixir.
- See what progress I have made in a year as an elixir developer.
Ace 0.1 (TCP echo)
The simplest TCP echo server that works. Checkout the source of version 0.1.0. The change log documents all enhancements to this prototype server.
Using Vagrant
Vagrant manages virtual machine provisioning.
Using Vagrant allows you to quickly get started with Ace
without needing to install Elixir/erlang on you machine.
If you do not know vagrant, or have it on your machine, I would suggest just installing Elixir on your machine and ignoring this section.
vagrant up
vagrant ssh
cd /vagrant
From this directory instructions will be that same as users running Elixir on their machine.
Contributing
Before opening a pull request, please open an issue first.
Once we’ve decided how to move forward with a pull request:
$ git clone git@github.com:CrowdHailer/Ace.git
$ cd Ace
$ mix deps.get
$ mix test
$ mix dialyzer.plt
$ mix dialyzer
Once you’ve made your additions, mix test
passes and mix dialyzer
reports no warnings, go ahead and open a PR!