libsocket.cc


Fichier texte: [libsocket.cc]

// -*- coding: latin-1 -*-

#include "libsocket.hh"
using std::string;

//------------------------------------------------------------------------------
// pour les includes de la bibliothèque C, il faut indiquer à C++ qu'il s'agit
// de fonctions C et non de fonctions C++.  Pour cette raison, il faut mettre
// les includes à l'intérieur d'un bloc spécial:
//
//         extern "C" { ... }
//------------------------------------------------------------------------------

extern "C"
{
  ???
}

//==============================================================================
// class ErrInfo
//
// que faire quand il se produit une erreur?  Différentes action peuvent être
// envisagées:
//
//     - ne rien faire
//     - recommencer l'opération, essayer autrement, ou faire autre chose
//     - afficher un message sur un terminal (par exemple avec `perror')
//     - ajouter un message à un fichier de log
//     - afficher un message dans une fenêtre graphique
//     - etc ...
//
// cette décision dépend de l'application et varie d'une application à une
// autre.  Si nous voulons une bibliothèque qui soit utilisable par n'importe
// quelle application, il faut qu'elle se contente de donner à l'application
// les informations sur une erreur, et c'est l'application elle-même qui
// choisira quoi faire de ces information.
//
// La classe `ErrInfo' est un conteneur destiné à prendre note des informations
// relatives à une erreur: le nom de la procédure dans laquelle s'est produite
// cette erreur (champ _proc) et le code de cette erreur (champ _code).
//==============================================================================

//------------------------------------------------------------------------------
// ErrInfo() le constructeur
//------------------------------------------------------------------------------

ErrInfo::ErrInfo() ???

//------------------------------------------------------------------------------
// errset(int code, string proc)
//
// prend note, dans les champs _proc et _code de l'objet ErrInfo, d'une erreur
// s'étant produite dans la procédure nommée `proc' et caractérisée par le code
// d'erreur `code'
//------------------------------------------------------------------------------

void ErrInfo::errset(int code, string proc)
{
  ???
}

//------------------------------------------------------------------------------
// errmsg(char* buf, int n)
//
// écrit dans le buffer `buf' de taille maximale `n' un message d'erreur appro-
// prié à l'erreur dont les informations sont enregistrées ici.  Vous vous
// servirez des fonctions `snprintf' etz `strerror' pour formatter ce message
// d'erreur.  On voudrait un message ayant la forme de ceux produit par `perror'
// par exemple:
//
// bind: permission refusée
//------------------------------------------------------------------------------

void ErrInfo::errmsg(char* buf, int n)
{
  ???
}

//==============================================================================
// class Socket
//
// Cette classe offre des méthodes d'utilisation simplifiée pour faire des
// opérations réseau.  Elle hérite également de `ErrInfo' pour nous permettre de
// prendre note facilement des informations relative à une erreur survenant
// durant une de ces opérations.  La classe `Socket' contient un champ `_fd'
// dans lequel on mettra le descripteur correspondant à la socket.  Les méthodes
// ci-dessous retournent 0 en cas de succès.  En cas d'échec elles retournent -1
// après avoir utilisé la méthode `errset' (voir ErrInfo) pour noter les détails
// de l'erreur.
//==============================================================================

//------------------------------------------------------------------------------
// Socket() le constructeur
//------------------------------------------------------------------------------

Socket::Socket() ???

//------------------------------------------------------------------------------
// socket()
//
// invoque l'appel système `socket' [cf. socket(2)] pour créer une socket:
// (1) dans le domaine de l'internet, (2) orientée "flux d'octets", et met son
// descripteur dans le champ `_fd'.  Pour indiquer à C++ que vous voulez appeler
// la fonction globale `socket' plutôt que la méthode `socket' de la classe, il
// faut écrire `::socket'
//------------------------------------------------------------------------------

int Socket::socket()
{
  ???
}

//------------------------------------------------------------------------------
// close()
//
// invoque l'appel système `close' [cf. close(2)] pour fermer la socket et
// libérer les ressources qui lui sont associées.
//------------------------------------------------------------------------------

int Socket::close()
{
  ???
}

//------------------------------------------------------------------------------
// bind(int port)
//
// invoque l'appel système `bind' [cf. bind(2)] pour lier la socket au `port'
// sur toutes les interfaces.  Cette méthode remplit une addresse de socket
// `struct sockaddr_in' [cf. ip(7)], puis l'utilise dans l'appel à `::bind'.
// N'oubliez pas les normalisations nécessaires à effectuer avec `htons' ou
// `htonl' [cf. htons(3)].
//------------------------------------------------------------------------------

int Socket::bind(int port)
{
  ???
}

//------------------------------------------------------------------------------
// listen(int backlog)
//
// invoque l'appel système `listen' [cf. listen(2)] pour indiquer qu'on va
// écouter sur cette socket; c'est à dire qu}on va y attendre des demandes de
// connexion de clients avec `accept'.  L'argument `backlog' est optionel et
// prend la valeur 10 par défaut quand il est omis (voir déclaration dans
// libsocket.hh).
//------------------------------------------------------------------------------

int Socket::listen(int backlog)
{
  ???
}

//------------------------------------------------------------------------------
// accept(Socket& client)
//
// invoque l'appel système `accept' [cf. accept(2)] pour attendre et accepter
// une connexion d'un client.  Il met alors le descripteur de la connexion dans
// le champ `_fd' de la socket `client' passée en argument.
//
// Notez que l'objet Socket client doit bien entendu avoir été déclaré (et donc
// instantié) avant d'appeler cette méthode à laquelle on le passe en argument.
//------------------------------------------------------------------------------

int Socket::accept(Socket& sock)
{
  ???
}

//------------------------------------------------------------------------------
// write(const char* buf, int n)
//
// écrire sur la socket exactement `n' octets pointés par `buf'.  C'est ce qu'on
// a fait en TD avec la fonction `write_exact'.
//------------------------------------------------------------------------------

int Socket::write(const char* buf, int n)
{
  ???
}

//------------------------------------------------------------------------------
// write(const char* buf)
//
// cette variante appelle la méthode précédente en calculant ell-même la
// longueur de la chaîne de caractères.
//------------------------------------------------------------------------------

int Socket::write(const char* buf)
{
  ???
}

//------------------------------------------------------------------------------
// write(string buf)
//
// cette variante appelle la précédente en convertissant l'argument `buf' de
// type `string' en `char*' grâce à la méthode `c_str()' des `string'.
//------------------------------------------------------------------------------

int Socket::write(string buf)
{
  ???
}

//==============================================================================
// class Server
//
// Cette classe offre une interface simplifiée pour fabriquer un serveur et le
// mettre en service en réseau.  Elle hérite de `Socket' pour intégrer la socket
// sur laquelle on va accepter les demandes de connexion de clients.
//==============================================================================

//------------------------------------------------------------------------------
// Server() le constructeur
//------------------------------------------------------------------------------

Server::Server() ???

//------------------------------------------------------------------------------
// run(int port)
//
// utilise les méthodes définies précédemment pour créer la socket, la lier au
// `port' sur toutes interfaces, et déclarer qu'on va écouter sur elle et y
// attendre les demandes de connexion de clients.
//
// ensuite, appelle la méthode `loop()' pour entamer la boucle de service des
// clients
//------------------------------------------------------------------------------

int Server::run(int port)
{
  ???
}

//------------------------------------------------------------------------------
// loop()
//
// méthode virtuelle (donc redéfinissable dans les classes dérivées)
// implémentant la boucle infinie qui accepte une connexion d'un client, invoque
// la méthode `interaction' pour traiter cette connexion, puis ferme la
// connexion.
//------------------------------------------------------------------------------

int Server::loop()
{
  ???
}