Archives pour mai, 2013

mongoose_64x64@2

Serveur web embarqué

0

Déployer une application web, ça n’est pas forcément ouvrir un site qui va accueillir des milliers de personnes et sera disponible sur internet, c’est aussi profiter d’une interface en client léger, et permettre à tous les périphériques du réseau local (ordinateurs, tablettes, téléphones …) d’accéder à votre application.

Cependant, même si de plus en plus de machines permettent de se trimbaler un système d’exploitation, telles que les Raspberry Pi notamment, déployer un serveur Apache et des scripts PHP « classiques » n’est pas toujours une très bonne idée, pour toutes les raisons de performances que l’on peut imaginer.

C’est pour cela qu’il est intéressant de disposer d’un serveur web léger et capable de s’interfacer facilement avec une application bas niveau, par exemple écrite en C++.

C’est en recherchant cela que je suis tombé sur mongoose, un serveur web embarqué qui tient en tout dans un unique fichier C et très léger. Il a d’ailleurs acquis une certaine popularité sur Github. Sur ma machine, il se compile en moins de 2 secondes et ses performances semblent très acceptables. Il supporte également plusieurs features avancés tels que l’upload de fichier ou les websockets.

Seul hic, le développement avec ce mongoose « brut » n’est pas très élégant, car il faut jongler avec des structures de données et une API en C. L’exemple de traitement des requêtes POST donne un peu mal à la tête.

C’est pour cela que j’ai créé un fork de mongoose afin d’y apporter une API C++ permettant d’utiliser beaucoup plus facilement les fonctionnalités du serveur web.

Exemple

Voici un hello world d’exemple, qui répond aux requêtes sur la page /hello?name=Nom en affichant le nom de l’utilisateur echappé:

#include <stdlib.h>
#include <signal.h>
#include <mongoose/Server.h>
#include <mongoose/WebController.h>

using namespace std;
using namespace Mongoose;

class MyController : public WebController
{
    public:
        void hello(Request &request, StreamResponse &response)
        {
            response << "Hello " << htmlEntities(request.get("name", "... what's your name ?")) << endl;
        }

        void setup()
        {
            addRoute("GET", "/hello", MyController, hello);
        }
};

int main()
{
    MyController myController;
    Server server(8080);
    server.registerController(&myController);

    server.start();

    while (1) {
        sleep(10);
    }
}

Dans cet exemple, un serveur web est créé, et sert par défaut les fichiers statiques du dossier www/ à partir du dossier d’exécution du serveur, sur le port 8080.

De plus, grâce à un système de contrôleur enregistré auprès du serveur, il répondra également aux requêtes GET sur l’URL /hello, en appelant la méthode hello du contrôleur.

La réponse hérite en fait ici de ostringstream, ce qui permet de lui ajouter des données simplement avec l’opérateur « << ».

Comme vous le voyez, accéder aux paramètres GET de la requête est aussi très facile à l’aide de request.get().

Comme on peut le voir dans un autre exemple plus complet, mon API permet également de manipuler des variables de sessions, les variables POST, et aussi de changer les en-têtes de la réponse.

Il est également possible de modifier le type de la réponse utilisée par les routes, et de créer ainsi par exemple un serveur web supportant une API JSON.

Application

Ce système peut permettre d’embarquer facilement un serveur web dans n’importe quelle application « lourde » C++. Et ce indépendamment de toute grosse bibliothèque qui pourrait exister (pour ne pas citer Qt ou boost par exemple).

C’est donc en effet approprié pour une utilisation dans l’embarqué comme par exemple une exécution à bord d’un petit ordinateur tel que la Raspberry Pi ou d’un MK802. Il pourrait être utilisé pour piloter un robot ou un appareil (routeur, télévision, serveur divers…).

Conclusions

Comme je risque de m’en servir dans de futurs projets, je compte continuer de maintenir mongoose-cpp et de merger mongoose de temps en temps pour rester à jour. J’aimerais aussi y ajouter une manière simple d’utiliser les websockets, comme cela est permis par mongoose.

Ce qui est assez remarquable, c’est l’intérêt de cette architecture qui utilise un outil très léger entièrement écrit en C pour y ajouter une fine couche d’ingénieurie logiciel, ce qui fait au final un outil à la fois performant et facile à utiliser. Implémenter un serveur web intégralement en C++ avec un génie logiciel au cordeau aurait sans doute donné une application nettement plus longue à compiler et moins performante.

Liens

devant

Debian sur la tablette ICOO D50 lite (A13, 50€)

1

Suite à mon précédent article, ou j’expliquais les péripéties pour installer Debian sur une tablette tactile, un des visiteurs, Ludo, m’a contacté afin que l’on s’entre-aide pour réussir à le faire fonctionner sur un autre modèle, la ICOO D50 lite.

Cette tablette coûte une cinquantaine d’euro et peut être trouvée sur DealExtreme :

On peut également observer à l’intérieur (merci à Ludo pour les photos) :

Elle intègre également le AllWinner A13, comme sur mon modèle, et comporte également un écran de 7″ (800×480), mais la carte WiFi est différente (RTL8188CUS) ainsi que le contrôle du tactile (GT811).

Après de nombreux tests nous avons fini par faire fonctionner un noyau Linux correct, avec le support du wifi et du tactile en natif ! Ce résultat ouvre donc plus de portes pour un prix plus bas.

Je n’ai pas (encore) pu tester l’image mais j’éspère le faire un jour

Téléchargements & liens

Merci à Ludo pour les échanges de mail et l’image !

Haut de page