From aecaf24c22013482de84ac6567249bec5ae7c78e Mon Sep 17 00:00:00 2001 From: dufourj Date: Sun, 1 May 2005 15:37:34 +0000 Subject: DataBuffer : Rajout du type de données Socket : Non-bloquant --- 2005/i/robert/src/data/data_buffer.cc | 14 ++- 2005/i/robert/src/data/data_buffer.hh | 25 +++- 2005/i/robert/src/socket/Makefile.defs | 2 +- 2005/i/robert/src/socket/socket_text.cc | 198 +++++++++++++++++++++----------- 2005/i/robert/src/socket/socket_text.hh | 35 ++++-- 2005/i/robert/src/socket/test_server.cc | 32 ++++-- 2005/i/robert/src/socket/test_socket.cc | 5 +- 7 files changed, 217 insertions(+), 94 deletions(-) (limited to '2005') diff --git a/2005/i/robert/src/data/data_buffer.cc b/2005/i/robert/src/data/data_buffer.cc index 4fc7c56..c0d8cef 100644 --- a/2005/i/robert/src/data/data_buffer.cc +++ b/2005/i/robert/src/data/data_buffer.cc @@ -32,24 +32,26 @@ static const unsigned min_size = 10; /// Constructeur par defaut DataBuffer::DataBuffer (void) - : size_ (min_size), headPos_ (0), tailPos_ (0) + : size_ (min_size), headPos_ (0), tailPos_ (0), type_ (NoType) { buffer_ = new uint8_t [size_]; } /// Constructeur par recopie. DataBuffer::DataBuffer (const DataBuffer &d) - : headPos_ (0) + : headPos_ (0), type_ (NoType) { unsigned sizeUse = d.tailPos_ - d.headPos_; size_ = tailPos_ = sizeUse; + type_ = d.type_; buffer_ = new uint8_t [size_]; std::memcpy (buffer_, &d.buffer_[headPos_], sizeUse); } /// Constructeur avec données. -DataBuffer::DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated) - : size_ (sizeAllocated), headPos_ (0), tailPos_ (size) +DataBuffer::DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated, + dataType_e type) + : size_ (sizeAllocated), headPos_ (0), tailPos_ (size), type_ (type) { if (!data || size > sizeAllocated) throw std::invalid_argument ("Paramêtres invalides"); @@ -110,7 +112,8 @@ DataBuffer::grow (const unsigned size) if (tailleLibre < size) { // On augmente de deux fois la taille - DataBuffer d (&buffer_[headPos_], tailPos_ - headPos_, 2 * size + size_); + DataBuffer d (&buffer_[headPos_], tailPos_ - headPos_, + 2 * size + size_, type_); d.swap (*this); } } @@ -123,4 +126,5 @@ DataBuffer::swap (DataBuffer &d) std::swap (size_, d.size_); std::swap (headPos_, d.headPos_); std::swap (tailPos_, d.tailPos_); + std::swap (type_, d.type_); } diff --git a/2005/i/robert/src/data/data_buffer.hh b/2005/i/robert/src/data/data_buffer.hh index 11724d8..5e6b55d 100644 --- a/2005/i/robert/src/data/data_buffer.hh +++ b/2005/i/robert/src/data/data_buffer.hh @@ -33,19 +33,33 @@ /// écriture. class DataBuffer : public DataInput, public DataOutput { + public: + /// Type de données possible du buffer. + enum dataType_e { + NoType, + Image + }; + private: /// Buffer de données. uint8_t *buffer_; /// Taille alloué en mémoire pour le buffer. unsigned size_; /// Position du début et de la fin des données dans le buffer. unsigned headPos_, tailPos_; + /// Type de données du buffer. + dataType_e type_; + /// Augmente la taille du buffer pour correspondre à size. + void grow (const unsigned size); + /// Echange les buffers. + void swap (DataBuffer &d); public: /// Constructeur par défaut. DataBuffer (void); /// Constructeur par recopie. DataBuffer (const DataBuffer &d); /// Constructeur avec données. - DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated); + DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated, + dataType_e type = NoType); /// Destructeur par défaut. ~DataBuffer (void) { delete [] buffer_; } /// Surcharge de l'opérateur d'affectation @@ -58,10 +72,9 @@ class DataBuffer : public DataInput, public DataOutput void write (const uint8_t *buf, unsigned size); /// Taille utile du buffer. unsigned size (void) const { return tailPos_ - headPos_; } - private: - /// Augmente la taille du buffer pour correspondre à size. - void grow (const unsigned size); - /// Echange les buffers. - void swap (DataBuffer &d); + /// Type de données du buffer. + dataType_e type (void) const { return type_; } + /// Change le type de données du buffer. + void setType (const dataType_e type) { type_ = type; } }; #endif // data_buffer_hh diff --git a/2005/i/robert/src/socket/Makefile.defs b/2005/i/robert/src/socket/Makefile.defs index 89d271f..c125e61 100644 --- a/2005/i/robert/src/socket/Makefile.defs +++ b/2005/i/robert/src/socket/Makefile.defs @@ -3,7 +3,7 @@ PROGRAMS += test_socket test_server net_OBJECTS = address.o server_socket.o socket_text.o test_socket_OBJECTS = test_socket.o $(net_OBJECTS) $(data_OBJECTS) -test_server_OBJECTS = test_server.o $(net_OBJECTS) $(data_OBJECTS) +test_server_OBJECTS = test_server.o $(net_OBJECTS) $(data_OBJECTS) $(image_OBJECTS) test_socket: $(test_socket_OBJECTS) test_server: $(test_server_OBJECTS) diff --git a/2005/i/robert/src/socket/socket_text.cc b/2005/i/robert/src/socket/socket_text.cc index 9c94509..da8a23b 100644 --- a/2005/i/robert/src/socket/socket_text.cc +++ b/2005/i/robert/src/socket/socket_text.cc @@ -26,29 +26,36 @@ #include "server_socket.hh" #include "address.hh" -#include "data/data_buffer.hh" #include #include +#include +#include + +/// Taille maximum du header +static const unsigned max_header_size = 10; /// Constructeur du serveur SocketText::SocketText (ServerSocket &ss) - : sendBufSize_ (0), recvTaille_ (0) +: recvBufPos_ (0), numMessageBuffer_ (0) { + headBuf_.resize (max_header_size); socket_ = ss.accept (); } /// Constructeur du serveur avec addresse SocketText::SocketText (ServerSocket &ss, Address &a) - : sendBufSize_ (0), recvTaille_ (0) +: recvBufPos_ (0), numMessageBuffer_ (0) { + headBuf_.resize (max_header_size); socket_ = ss.accept (a); } /// Constructeur du client SocketText::SocketText (const Address &a) - : sendBufSize_ (0), recvTaille_ (0) +: recvBufPos_ (0), numMessageBuffer_ (0) { + headBuf_.resize (max_header_size); // Création du socket socket_ = socket (AF_INET, SOCK_STREAM, 0); if (socket_ == -1) @@ -62,12 +69,16 @@ SocketText::SocketText (const Address &a) SocketText & SocketText::operator<< (const DataBuffer &d) { + // Copie du buffer DataBuffer db (d); + // Récupération de la taille du message unsigned size = db.size (); - std::vector v; - v.resize (size); - db.read ((uint8_t*) &v[0], size); - send (&v[0], size); + // Données du buffer + std::vector data (size); + // On y place les données dedans + db.read ((uint8_t*) &data[0], size); + // Encode les données et le places dans le buffer d'envoie + encode (&data[0], size, db.type ()); return *this; } @@ -75,92 +86,151 @@ SocketText::operator<< (const DataBuffer &d) SocketText & SocketText::operator>> (DataBuffer &d) { - std::vector v; - recv (v); - d.write ((uint8_t*) &v[0], v.size ()); + if (numMessageBuffer_ > 0) + { + // Récupération des informations du message qu'on veut retirer + unsigned int size = messList_.begin ()->size; + d.setType (messList_.begin ()->type); + // Récupération du message depuis le buffer + std::vector v (size); + std::memcpy (&v[0], &recvBuf_[0], size); + // Ecriture des données dans le buffer + d.write ((uint8_t*) &v[0], v.size ()); + // Suppression du message du buffer + recvBuf_.erase (recvBuf_.begin (), recvBuf_.begin () + size); + messList_.erase (messList_.begin ()); + bufferOldSize_ -= size; + bufferCurSize_ -= size; + recvBufPos_ -= size; + numMessageBuffer_--; + } return *this; } -/// Envoie d'un tableau de données (data) de taille size. +/// Envoie des données du buffer. int -SocketText::send (const char *data, const int size) +SocketText::send (void) { - int ss; int status; - int dataSend = 0; - // Encodage, ss = taille (message + header) - ss = size + encodeMsg (data, size); - do + status = ::send (socket_, &sendBuf_[0], sendBuf_.size (), MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) { - status = ::send (socket_, &sendBuf_[0], ss - dataSend, MSG_NOSIGNAL); - dataSend += status; - } while (status >= 0 && size >= dataSend); - return status < 0 ? -1 : dataSend; + throw std::runtime_error ("Erreur de send de socket"); + } + if (status >= 0) + { + if (status != 0) + sendBuf_.erase (sendBuf_.begin (), sendBuf_.begin () + status); + return status; + } + return -1; } /// Encodage du message (rajout du header) -int -SocketText::encodeMsg (const char *data, const int size) +void +SocketText::encode (const char *data, const int size, + const DataBuffer::dataType_e type) { - // Création du header + // Création du header (1H4242H) std::ostringstream o; + // Rajout du type + if (!(o << type)) + throw std::runtime_error ("Erreur de convertion int -> string"); o << "H"; if (!(o << size )) throw std::runtime_error ("Erreur de convertion int -> string"); o << "H"; + // Recopie du header dans le buffer 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; + std::string::const_iterator sEnd = s.end (); + unsigned int compt = 0; + std::string::const_iterator i = s.begin (); + // Ecriture d'un header de taille fixe + while (compt < max_header_size) + { + if (i != sEnd) + { + sendBuf_.push_back (*i); + i++; + } + else + sendBuf_.push_back ('H'); + compt++; + } + // Rajout des données dans le buffer + for (int i = 0; i < size; i++) + sendBuf_.push_back (data[i]); +} + +/// Décodage du header. +int +SocketText::decode (void) +{ + mess_t header; + header.type = (DataBuffer::dataType_e) std::atoi (&headBuf_[0]); + header.size = std::atoi (&headBuf_[2]); + messList_.push_back (header); + return header.size; } /// Reception de données dans un vecteur. -void SocketText::recv (std::vector &v) +bool +SocketText::recv () { // 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; + static unsigned int headerPos = 0; - // On n'a pas reçu la taille encore - if (headerStatus != 2) + // On n'a pas reçu encore de quoi faire un header + if (headerPos < max_header_size) { - // 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); + status = ::recv (socket_, &headBuf_[headerPos], + max_header_size - headerPos, MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + throw std::runtime_error ("Erreur de send de socket"); + if (status > 0) + headerPos += status; } - // Récupération de la taille du message du header - if (headerStatus == 2 && recvTaille_ == 0) + // Décodage du header + if (headerPos == max_header_size) { - recvTaille_ = atoi (&headBuf_[1]); - pos = 0; - recvBuf_.resize (recvTaille_); + bufferOldSize_ = recvBuf_.size (); + bufferCurSize_ = bufferOldSize_ + decode (); + recvBuf_.resize (bufferCurSize_); + headerPos ++; } - if (recvTaille_) + // Récupération du message lui-même + if (headerPos > max_header_size) { - // 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_) + status = ::recv (socket_, &recvBuf_[recvBufPos_], + bufferCurSize_ - recvBufPos_, MSG_NOSIGNAL); + if (status == -1 && errno != EWOULDBLOCK) + throw std::runtime_error ("Erreur de send de socket"); + if (status > 0) + recvBufPos_ += status; + if (recvBufPos_ == bufferCurSize_) { - v = recvBuf_; - headerStatus = posHeader = recvTaille_ = 0; + headerPos = 0; + numMessageBuffer_++; } } + return numMessageBuffer_ > 0; +} + +/// Changement du bloquant non/bloquant. +void +SocketText::nonblock (bool flag) +{ + // Récupération de l'ancien flag. + int old = fcntl (socket_, F_GETFL, 0); + if (old == -1) + throw std::runtime_error ("Erreur de fcntl"); + // Change le flag. + if (flag) + old |= O_NONBLOCK; + else + old &= ~O_NONBLOCK; + // Ecrit le nouveau flag. + if (fcntl (socket_, F_SETFL, old) == -1) + throw std::runtime_error ("Erreur de fcntl"); } diff --git a/2005/i/robert/src/socket/socket_text.hh b/2005/i/robert/src/socket/socket_text.hh index c31e38a..b734753 100644 --- a/2005/i/robert/src/socket/socket_text.hh +++ b/2005/i/robert/src/socket/socket_text.hh @@ -24,26 +24,39 @@ // Email: // }}} -#include - class ServerSocket; -class DataBuffer; class Address; +#include "data/data_buffer.hh" + +#include class SocketText { + /// Structure pour stocker les informations d'un message. + typedef struct { + unsigned int size; + DataBuffer::dataType_e type; + } mess_t; + std::vector messList_; /// L'identificateur du socket. int socket_; /// Buffer pour le header. - char headBuf_[10]; + std::vector headBuf_; /// 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_; + unsigned int recvBufPos_; + unsigned int bufferOldSize_; + unsigned int bufferCurSize_; + /// Nombre de message dans le buffer + int numMessageBuffer_; + DataBuffer::dataType_e type_; /// Encodage du message (rajout du header) - int encodeMsg (const char *data, const int size); + void encode (const char *data, const int size, + const DataBuffer::dataType_e type); + /// Décodage du header. + int decode (void); public: /// Constructeur du serveur. @@ -56,10 +69,12 @@ class SocketText { 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); + /// Envoie des données du buffer. + int send (void); /// Reception de données dans un vecteur. - void recv (std::vector &v); + bool recv (void); + /// Changement du bloquant non/bloquant. + void nonblock (bool flag = true); }; #endif // socket_text_hh diff --git a/2005/i/robert/src/socket/test_server.cc b/2005/i/robert/src/socket/test_server.cc index 479dbca..40224a7 100644 --- a/2005/i/robert/src/socket/test_server.cc +++ b/2005/i/robert/src/socket/test_server.cc @@ -26,6 +26,8 @@ #include "socket_text.hh" #include "data/data_input_file.hh" #include "data/data_buffer.hh" +#include "image/raw_reader.hh" +#include "image/image.hh" #include #include @@ -42,17 +44,33 @@ main (int argc, char **argv) ServerSocket ss (atoi (argv[1])); Address a; SocketText st (ss, a); + st.nonblock (); // DataBuffer de reception DataBuffer db; // Reception des données + while (!st.recv ()); 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 ()); + if (db.type () != DataBuffer::Image) + throw std::runtime_error ("Echec de la transmission"); + RawReader reader (db, 360, 296, Image::rgb); + Image img (360, 296, Image::rgb); + img.read (reader); + std::ofstream file (argv[2]); + file.write ((char*) img.getBuf (), img.getBufSize ()); + +// // 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 ()); +// DataBuffer db1; +// // Reception des données +// while (!st.recv ()); +// st >> db1; +// std::cout << ">> Reçu " << db1.size () << " bits." << std::endl; +// if (db1.type () != DataBuffer::Image) +// throw std::runtime_error ("Echec de la transmission"); } catch (const std::runtime_error &r) { diff --git a/2005/i/robert/src/socket/test_socket.cc b/2005/i/robert/src/socket/test_socket.cc index f68b555..01c853a 100644 --- a/2005/i/robert/src/socket/test_socket.cc +++ b/2005/i/robert/src/socket/test_socket.cc @@ -46,12 +46,15 @@ main (int argc, char **argv) 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 ()); + DataBuffer db (&img[0], img.size (), img.size (), + DataBuffer::Image); // Création du socket char *h = argv[1]; SocketText st (Address (h, atoi (argv[2]))); + st.nonblock (); // Envoie des données st << db; + while (st.send () != 0); } catch (const std::runtime_error &r) { -- cgit v1.2.3