From c50955765bfd033c8be61bff6132a1b2ba5c2eb3 Mon Sep 17 00:00:00 2001 From: dufourj Date: Fri, 29 Apr 2005 20:45:52 +0000 Subject: Ajout des fichers du dossier socket pour le réseau * Address : gestion des structures d'adresse pour les sockets, * SocketText : socket qui écrit en texte sur le réseau, * SocketServer : serveur qui écoute sur un port. La classe SocketText ne gére pas les sockets non bloquants. Les fonctions recv/sent sont donc à revoir. --- 2005/i/robert/src/socket/address.cc | 93 +++++++++++++++++ 2005/i/robert/src/socket/address.hh | 76 ++++++++++++++ 2005/i/robert/src/socket/server_socket.cc | 86 ++++++++++++++++ 2005/i/robert/src/socket/server_socket.hh | 47 +++++++++ 2005/i/robert/src/socket/socket_text.cc | 166 ++++++++++++++++++++++++++++++ 2005/i/robert/src/socket/socket_text.hh | 65 ++++++++++++ 2005/i/robert/src/socket/test_server.cc | 69 +++++++++++++ 2005/i/robert/src/socket/test_socket.cc | 68 ++++++++++++ 8 files changed, 670 insertions(+) create mode 100644 2005/i/robert/src/socket/address.cc create mode 100644 2005/i/robert/src/socket/address.hh create mode 100644 2005/i/robert/src/socket/server_socket.cc create mode 100644 2005/i/robert/src/socket/server_socket.hh create mode 100644 2005/i/robert/src/socket/socket_text.cc create mode 100644 2005/i/robert/src/socket/socket_text.hh create mode 100644 2005/i/robert/src/socket/test_server.cc create mode 100644 2005/i/robert/src/socket/test_socket.cc (limited to '2005') diff --git a/2005/i/robert/src/socket/address.cc b/2005/i/robert/src/socket/address.cc new file mode 100644 index 0000000..4567e2e --- /dev/null +++ b/2005/i/robert/src/socket/address.cc @@ -0,0 +1,93 @@ +// address.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "address.hh" + +#include +#include + +/// Constructeur par défaut. +Address::Address (void) + : port_ (0) +{ + resolv (); +} + +/// Constructeur avec le port (serveur) +Address::Address (const int port) + : port_ (port) +{ + resolv (); +} +/// Constructeur avec hôte et port. +Address::Address (const std::string &host, const int port) + : host_ (host), port_ (port) +{ + resolv (); +} + +/// Constructeur à partir de la strcuture d'adresse. +Address::Address (const sockaddr *sa, socklen_t sl) +{ + // On vérifie que c'est vraiment un struct sockaddr_in + if (sl != sizeof (sockaddr_in)) + throw std::invalid_argument ("Invalide Adresse"); + sa_ = * reinterpret_cast (sa); +} + +/// Résolution de la structure d'adresse depuis l'hôte/port +void +Address::resolv (void) +{ + // Cas du serveur, pas d'hôte + if (host_.empty ()) + sa_.sin_addr.s_addr = htonl (INADDR_ANY); + else + { + // Convertion de l'hôte en structure adresse + if (!inet_pton (AF_INET, host_.c_str (), &sa_.sin_addr)) + { + hostent *host_info = gethostbyname (host_.c_str ()); + if (!host_info) + throw std::runtime_error (host_ + " : Hôte inconnue"); + } + } + sa_.sin_family = AF_INET; + // Convertion pour le passage sur le réseau + sa_.sin_port = htons (port_); +} + +/// Résolution de l'hôte/port depuis la structure d'adresse +void +Address::unresolv (void) +{ + hostent *host_info; + // Recherche de l'hôte + host_info = gethostbyaddr (reinterpret_cast (&(sa_.sin_addr)), sizeof sa_.sin_addr, AF_INET); + if (!host_info) + host_ = inet_ntoa (sa_.sin_addr); + else + host_ = host_info->h_name; + // Recherche du port + port_ = ntohs (sa_.sin_port); +} diff --git a/2005/i/robert/src/socket/address.hh b/2005/i/robert/src/socket/address.hh new file mode 100644 index 0000000..53fca07 --- /dev/null +++ b/2005/i/robert/src/socket/address.hh @@ -0,0 +1,76 @@ +#ifndef address_hh +#define address_hh +// address.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include +#include +#include +#include + +#include +#include + +/// S'occupe de gérer les adresses. +class Address { + /// La structure sockaddr_in de type réseau/AF_INET. + sockaddr_in sa_; + /// Le nom d'hôte de l'adresse. + std::string host_; + /// Le numéro de port de l'adresse. + int port_; + + public: + /// Constructeur par défaut. + Address (void); + /// Constructeur pour le serveur. (port seulement) + Address (const int port); + /// Constructeur avec hôte et port. + Address (const std::string &host, const int port); + /// Constructeur à partir de la structure d'adresse. + Address (const sockaddr *sa, socklen_t sl); + /// Geter sockaddr. + const sockaddr *getSockaddr (void) const { return + reinterpret_cast (&sa_); } + /// Geter hôte. + const std::string &getHost (void) const { return host_; } + /// Geter port. + const int getPort (void) const { return port_; } + + private: + /// Résolution adresse vers hôte/port + void resolv (void); + /// Résolution hôte/port vers adresse + void unresolv (void); + +}; + +/// Surcharge de l'opérateur << pour l'affichage. +inline std::ostream & +operator<< (std::ostream &s, const Address &a) +{ + return s << a.getHost () << ':' << a.getPort (); +} + +#endif // address_hh diff --git a/2005/i/robert/src/socket/server_socket.cc b/2005/i/robert/src/socket/server_socket.cc new file mode 100644 index 0000000..539b94e --- /dev/null +++ b/2005/i/robert/src/socket/server_socket.cc @@ -0,0 +1,86 @@ +// server_socket.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "server_socket.hh" + +#include "address.hh" + +#include +#include +#include + +/// Constructeur par défaut. +ServerSocket::ServerSocket (int port) +{ + bind (port); +} + +/// Bind le serveur sur un port d'écoute. +void +ServerSocket::bind (int port) +{ + static const int reuse_s = 1; + // Adresse sur un port (pas d'hote, écoutera de partout) + Address a (port); + // Création du socket IPv4 - TCP + socket_ = socket (PF_INET, SOCK_STREAM, 0); + if (socket_ == -1) + throw std::runtime_error ("Erreur de création du socket"); + // Socket réutilisable en cas d'arret "brutale" + if (setsockopt (socket_, SOL_SOCKET, SO_REUSEADDR, + &reuse_s, sizeof (int)) == -1) + throw std::runtime_error ("Erreur setsockopt : reusable"); + // Bindage du socket sur le port et l'adresse + if (::bind (socket_, a.getSockaddr (), sizeof (struct sockaddr_in)) == -1) + throw std::runtime_error ("Erreur de bind du socket"); + // On met le socket en attente de connexion + if (listen (socket_, 0) == -1) + throw std::runtime_error ("Erreur de listen"); +} + +// Accepte une nouvelle connexion. +int +ServerSocket::accept (void) const +{ + int s = ::accept (socket_, 0, 0); + if (s == -1) + throw std::runtime_error ("Erreur d'accept de nouvelles connexions"); + return s; +} + +// Accepte une nouvelle connexion et remplie Address. +int +ServerSocket::accept (Address &a) const +{ + sockaddr_in sa; + socklen_t sl = sizeof sa; + int s = ::accept (socket_, reinterpret_cast (&sa), + &sl); + if (s == -1) + { + throw std::runtime_error ("Erreur d'accept nouvelle connexion"); + } + // Récupération de l'adresse + a = Address (reinterpret_cast (&sa), sl); + return s; +} diff --git a/2005/i/robert/src/socket/server_socket.hh b/2005/i/robert/src/socket/server_socket.hh new file mode 100644 index 0000000..995ad01 --- /dev/null +++ b/2005/i/robert/src/socket/server_socket.hh @@ -0,0 +1,47 @@ +#ifndef server_socket_hh +#define server_socket_hh +// server_socket.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include +class Address; + +/// Créer un server TCP pour le transfert des données. +class ServerSocket { + private: + /// L'identificateur du socket. + int socket_; + /// Bind le serveur sur un port d'écoute. + void bind (int port); + public: + /// Constructeur par défaut. + ServerSocket (int port); + /// Destructeur. + ~ServerSocket () { close (socket_); } + /// Accepte une nouvelle connexion et remplie Address. + int accept (Address &a) const; + /// Accepte une nouvelle connexion. + int accept (void) const; +}; +#endif // server_socket_hh diff --git a/2005/i/robert/src/socket/socket_text.cc b/2005/i/robert/src/socket/socket_text.cc new file mode 100644 index 0000000..9c94509 --- /dev/null +++ b/2005/i/robert/src/socket/socket_text.cc @@ -0,0 +1,166 @@ +// socket_text.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "socket_text.hh" + +#include "server_socket.hh" +#include "address.hh" +#include "data/data_buffer.hh" + +#include +#include + +/// Constructeur du serveur +SocketText::SocketText (ServerSocket &ss) + : sendBufSize_ (0), recvTaille_ (0) +{ + socket_ = ss.accept (); +} + +/// Constructeur du serveur avec addresse +SocketText::SocketText (ServerSocket &ss, Address &a) + : sendBufSize_ (0), recvTaille_ (0) +{ + socket_ = ss.accept (a); +} + +/// Constructeur du client +SocketText::SocketText (const Address &a) + : sendBufSize_ (0), recvTaille_ (0) +{ + // Création du socket + socket_ = socket (AF_INET, SOCK_STREAM, 0); + if (socket_ == -1) + throw std::runtime_error ("Erreur de création de socket"); + // Connexion au serveur + if (connect (socket_, a.getSockaddr (), sizeof (sockaddr_in)) == -1) + throw std::runtime_error ("Erreur de connexion au serveur"); +} + +/// Envoie d'un buffer de données. +SocketText & +SocketText::operator<< (const DataBuffer &d) +{ + DataBuffer db (d); + unsigned size = db.size (); + std::vector v; + v.resize (size); + db.read ((uint8_t*) &v[0], size); + send (&v[0], size); + return *this; +} + +/// Reception d'un buffer de données. +SocketText & +SocketText::operator>> (DataBuffer &d) +{ + std::vector v; + recv (v); + d.write ((uint8_t*) &v[0], v.size ()); + return *this; +} + +/// Envoie d'un tableau de données (data) de taille size. +int +SocketText::send (const char *data, const int size) +{ + int ss; + int status; + int dataSend = 0; + // Encodage, ss = taille (message + header) + ss = size + encodeMsg (data, size); + do + { + status = ::send (socket_, &sendBuf_[0], ss - dataSend, MSG_NOSIGNAL); + dataSend += status; + } while (status >= 0 && size >= dataSend); + return status < 0 ? -1 : dataSend; +} + +/// Encodage du message (rajout du header) +int +SocketText::encodeMsg (const char *data, const int size) +{ + // Création du header + std::ostringstream o; + o << "H"; + if (!(o << size )) + throw std::runtime_error ("Erreur de convertion int -> string"); + o << "H"; + std::string s = o.str (); + int ss = s.size (); + // Re-Allocation du buffer d'envoye + sendBuf_.resize (ss + size); + // Copie du header + strncpy (&sendBuf_[0], s.c_str (), ss); + // Copie du message + strncpy (&sendBuf_[ss], data, size); + return ss; +} + +/// Reception de données dans un vecteur. +void SocketText::recv (std::vector &v) +{ + // FIXME C'est KK + int status; + static unsigned int pos = 0; + static unsigned int posHeader = 0; + // 0 : pas reçu, 1 : partiellement reçu, 2 : reçu + static int headerStatus = 0; + + // On n'a pas reçu la taille encore + if (headerStatus != 2) + { + // Récupération des données une par une. + do + { + status = ::recv (socket_, &headBuf_[posHeader], 1, MSG_NOSIGNAL); + if (headBuf_[posHeader++] == 'H') + headerStatus ++; + } while (status > 0 && headerStatus != 2); + } + // Récupération de la taille du message du header + if (headerStatus == 2 && recvTaille_ == 0) + { + recvTaille_ = atoi (&headBuf_[1]); + pos = 0; + recvBuf_.resize (recvTaille_); + } + if (recvTaille_) + { + // Récupération du message lui-même + do + { + status = ::recv (socket_, &recvBuf_[pos], recvTaille_, + MSG_NOSIGNAL); + if (status > 0) + pos += status; + } while (status > 0 && pos < recvTaille_); + if (pos == recvTaille_) + { + v = recvBuf_; + headerStatus = posHeader = recvTaille_ = 0; + } + } +} diff --git a/2005/i/robert/src/socket/socket_text.hh b/2005/i/robert/src/socket/socket_text.hh new file mode 100644 index 0000000..c31e38a --- /dev/null +++ b/2005/i/robert/src/socket/socket_text.hh @@ -0,0 +1,65 @@ +#ifndef socket_text_hh +#define socket_text_hh +// socket_text.hh +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include + +class ServerSocket; +class DataBuffer; +class Address; + +class SocketText { + /// L'identificateur du socket. + int socket_; + /// Buffer pour le header. + char headBuf_[10]; + /// Buffer de reception de données. + std::vector recvBuf_; + /// Buffer d'émission de données. + std::vector sendBuf_; + /// Taille des buffers d'E/S XXX + unsigned int sendBufSize_; + unsigned int recvTaille_; + /// Encodage du message (rajout du header) + int encodeMsg (const char *data, const int size); + + public: + /// Constructeur du serveur. + SocketText (ServerSocket &ss); + /// Constructeur du serveur avec addresse. + SocketText (ServerSocket &ss, Address &a); + /// Constructeur du client. + SocketText (const Address &a); + /// Envoie d'un buffer de données. + SocketText &operator<< (const DataBuffer &d); + /// Reception d'un buffer de données. + SocketText &operator>> (DataBuffer &d); + /// Envoie d'un tableau de données (data) de taille size. + int send (const char *data, const int size); + /// Reception de données dans un vecteur. + void recv (std::vector &v); +}; + +#endif // socket_text_hh diff --git a/2005/i/robert/src/socket/test_server.cc b/2005/i/robert/src/socket/test_server.cc new file mode 100644 index 0000000..479dbca --- /dev/null +++ b/2005/i/robert/src/socket/test_server.cc @@ -0,0 +1,69 @@ +// test_socket.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} +#include "server_socket.hh" +#include "address.hh" +#include "socket_text.hh" +#include "data/data_input_file.hh" +#include "data/data_buffer.hh" + +#include +#include +#include + +int +main (int argc, char **argv) +{ + if (argc == 3) + { + try + { + // Serveur + ServerSocket ss (atoi (argv[1])); + Address a; + SocketText st (ss, a); + // DataBuffer de reception + DataBuffer db; + // Reception des données + st >> db; + std::cout << ">> Reçu " << db.size () << " bits." << std::endl; + // Récupération des données du DataBuffer + std::vector v (db.size ()); + db.read ((uint8_t*) &v[0], db.size ()); + // Ecriture dans le fichier + std::ofstream file (argv[2]); + file.write (&v[0], v.size ()); + } + catch (const std::runtime_error &r) + { + std::cerr << argv[0] << ": " << r.what () << std::endl; + return 1; + } + } + else + { + std::cerr << "Syntaxe: " << argv[0] << " port out_file" << std::endl; + return 1; + } + return 0; +} diff --git a/2005/i/robert/src/socket/test_socket.cc b/2005/i/robert/src/socket/test_socket.cc new file mode 100644 index 0000000..f68b555 --- /dev/null +++ b/2005/i/robert/src/socket/test_socket.cc @@ -0,0 +1,68 @@ +// test_socket.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Dufour Jérémy +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Contact : +// Web: %WEB% +// Email: +// }}} + +#include "server_socket.hh" +#include "address.hh" +#include "socket_text.hh" +#include "data/data_input_file.hh" +#include "data/data_buffer.hh" + +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + if (argc == 4) + { + try + { + // Récupération des données du fichier + DataInputFile df (argv[3]); + std::vector img (319680); + df.read (&img[0], 319680); + // Ecriture des données du fichier dans le buffer + DataBuffer db (&img[0], img.size (), img.size ()); + // Création du socket + char *h = argv[1]; + SocketText st (Address (h, atoi (argv[2]))); + // Envoie des données + st << db; + } + catch (const std::runtime_error &r) + { + std::cerr << argv[0] << ": " << r.what () << std::endl; + return 1; + } + } + else + { + std::cerr << "Syntaxe: " << argv[0] << " host port in_file" << + std::endl; + return 1; + } +} -- cgit v1.2.3